diff --git a/.gitignore b/.gitignore
index 6c4c3f0c..8d6f5252 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,5 +9,4 @@ Builds
.idea/
*.iml
/local.properties
-*.apk
*.DS_Store
diff --git a/README.md b/README.md
index d6f64ad5..e5c6cbf2 100644
--- a/README.md
+++ b/README.md
@@ -24,13 +24,14 @@ Simplicity Connect includes many demos to test sample apps in the Silicon Labs G
- **Health Thermometer**: Connect to a BLE hardware kit and receive the temperature data from the on-board sensor.
- **Connected Lighting DMP**: Leverage the dynamic multi-protocol (DMP) sample apps to control a DMP light node from a mobile and protocol-specific switch node (Zigbee, proprietary) while keeping the light status in sync across all devices.
- **Range Test**: Visualize the RSSI and other RF performance data on the mobile phone while running the Range Test sample application on a pair of Silicon Labs radio boards.
-- **Motion**: Control a 3D render of a Silicon Labs Thunderboard or Dev Kit that follows the phyiscal board movements.
+- **Motion**: Control a 3D render of a Silicon Labs Thunderboard or Dev Kit that follows the physical board movements.
- **Environment**: Read and display the data from the on-board sensors on a Silicon Labs Thunderboard or Dev Kit.
- **Wi-Fi Commissioning**: Commission a Wi-Fi device over BLE.
- **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.
+- **Wi-Fi Throughput**: Wi-Fi demo feature for measuring data throughput between SiWx91x device and the mobile phone.
## 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 f65e0f89..78b37a5d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,10 +2,10 @@
plugins {
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
- id("com.google.dagger.hilt.android") version "2.45" apply false
+ id("org.jetbrains.kotlin.android") version "1.9.21" apply false
+ id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.21" apply false
+ id("org.jetbrains.kotlin.kapt") version "1.9.21" apply false
+ id("com.google.dagger.hilt.android") version "2.51.1" apply false
}
buildscript {
diff --git a/build/Si-Connect - v3_0_0.apk b/build/Si-Connect - v3_0_0.apk
new file mode 100644
index 00000000..2fcd719a
--- /dev/null
+++ b/build/Si-Connect - v3_0_0.apk
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e3674b2cae4575ccb76b171d04e0f7312d32f35aea94b362475d52286a573af0
+size 71947367
diff --git a/gradle.properties b/gradle.properties
index 9a84b0ad..a525f3cc 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -10,7 +10,7 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
-org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
@@ -18,6 +18,5 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro
org.gradle.parallel=true
android.enableJetifier=true
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 d96216a6..ee78cf57 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#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
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/mobile/build.gradle.kts b/mobile/build.gradle.kts
index 8fd4bf76..325139ca 100644
--- a/mobile/build.gradle.kts
+++ b/mobile/build.gradle.kts
@@ -1,9 +1,7 @@
-import com.android.build.api.variant.Packaging
-
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
- id("org.jetbrains.kotlin.android.extensions")
+ id("org.jetbrains.kotlin.plugin.parcelize")
id("org.jetbrains.kotlin.kapt")
id("com.google.dagger.hilt.android")
}
@@ -25,7 +23,7 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
- packagingOptions { jniLibs { useLegacyPackaging = true } }
+ packaging { jniLibs { useLegacyPackaging = true } }
buildTypes {
release {
@@ -36,13 +34,21 @@ android {
ndk {
abiFilters.add("armeabi-v7a")
abiFilters.add("arm64-v8a")
+ abiFilters.add("x86-64")
+ abiFilters.add("x86")
}
}
debug {
isDebuggable = true
- //renderscriptDebuggable false
- //minifyEnabled true
- //pseudoLocalesEnabled false
+ }
+ }
+
+ applicationVariants.all{
+ assembleProvider.get().doLast{
+ copy{
+ from("Builds/${rootProject.name}/${project.name}/outputs/apk/Si-Connect/release/mobile-Si-Connect-release.apk")
+ into ("Builds")
+ }
}
}
@@ -60,23 +66,38 @@ android {
create("Si-Connect") {
dimension = versionDim
applicationId = "com.siliconlabs.bledemo"
- versionCode = 55
- versionName = "2.9.3"
+ versionCode = 56
+ versionName = "3.0.0"
}
}
compileOptions {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = JavaVersion.VERSION_1_8.toString()
+ jvmTarget = JavaVersion.VERSION_17.toString()
+ }
+
+ kapt {
+ correctErrorTypes = true
+ }
+
+ sourceSets {
+ getByName("main") {
+ jniLibs.srcDir("libs")
+ }
}
buildFeatures {
viewBinding = true
buildConfig = true
+ compose = true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = "1.5.7"
}
}
@@ -86,21 +107,21 @@ dependencies {
// 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:review:2.0.2")
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:review-ktx:2.0.2")
implementation("com.google.android.play:app-update-ktx:2.1.0")
// androidx
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.7.0")
- implementation("androidx.fragment:fragment:1.8.1")
+ implementation("androidx.fragment:fragment:1.8.3")
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("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6")
+ implementation("androidx.activity:activity-ktx:1.9.2")
implementation("com.google.android.material:material:1.12.0")
// Coroutines
@@ -121,13 +142,13 @@ dependencies {
//implementation("com.github.PhilJay:MPAndroidChart:v3.0.3")
// Navigation
- 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")
+ implementation("androidx.navigation:navigation-fragment-ktx:2.8.1")
+ implementation("androidx.navigation:navigation-ui-ktx:2.8.1")
+ implementation("androidx.navigation:navigation-dynamic-features-fragment:2.8.1")
// Dependency injection
- implementation("com.google.dagger:hilt-android:2.46.1")
- kapt("com.google.dagger:hilt-android-compiler:2.45")
+ implementation("com.google.dagger:hilt-android:2.51.1")
+ kapt("com.google.dagger:hilt-android-compiler:2.51.1")
// View binding
implementation("com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.9")
@@ -138,7 +159,7 @@ dependencies {
// Parsing
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.opencsv:opencsv:5.6")
- implementation("androidx.activity:activity:1.9.0")
+ implementation("androidx.activity:activity:1.9.2")
// Only used for Int.pow() method in a couple of places
implementation("com.google.guava:guava:29.0-android")
@@ -160,12 +181,24 @@ dependencies {
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")
+ implementation("com.google.mlkit:barcode-scanning:17.3.0")
//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")
- implementation ("com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2")
+ implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.6")
+
+ implementation ("com.daimajia.swipelayout:library:1.2.0@aar")
+
+ //JetPack compose
+ val composeBom = platform("androidx.compose:compose-bom:2024.06.00")
+ implementation(composeBom)
+ androidTestImplementation(composeBom)
+ implementation("androidx.compose.ui:ui")
+ implementation("androidx.compose.material:material")
+ implementation("androidx.compose.ui:ui-tooling-preview")
+ implementation("androidx.activity:activity-compose")
+ androidTestImplementation("androidx.compose.ui:ui-test-junit4")
+ debugImplementation("androidx.compose.ui:ui-tooling")
+
}
diff --git a/mobile/libs/AndroidPlatform.jar b/mobile/libs/AndroidPlatform.jar
index b88b1546..4fecdaca 100644
Binary files a/mobile/libs/AndroidPlatform.jar and b/mobile/libs/AndroidPlatform.jar differ
diff --git a/mobile/libs/CHIPClusterID.jar b/mobile/libs/CHIPClusterID.jar
new file mode 100644
index 00000000..68fd4765
Binary files /dev/null and b/mobile/libs/CHIPClusterID.jar differ
diff --git a/mobile/libs/CHIPClusters.jar b/mobile/libs/CHIPClusters.jar
new file mode 100644
index 00000000..acb9f2a4
Binary files /dev/null and b/mobile/libs/CHIPClusters.jar differ
diff --git a/mobile/libs/CHIPController.jar b/mobile/libs/CHIPController.jar
index bc33c98e..92dd011e 100644
Binary files a/mobile/libs/CHIPController.jar and b/mobile/libs/CHIPController.jar differ
diff --git a/mobile/libs/CHIPInteractionModel.jar b/mobile/libs/CHIPInteractionModel.jar
new file mode 100644
index 00000000..744624be
Binary files /dev/null and b/mobile/libs/CHIPInteractionModel.jar differ
diff --git a/mobile/libs/OnboardingPayload.jar b/mobile/libs/OnboardingPayload.jar
new file mode 100644
index 00000000..e4775b60
Binary files /dev/null and b/mobile/libs/OnboardingPayload.jar differ
diff --git a/mobile/libs/libMatterJson.jar b/mobile/libs/libMatterJson.jar
new file mode 100644
index 00000000..504ce3e5
Binary files /dev/null and b/mobile/libs/libMatterJson.jar differ
diff --git a/mobile/libs/libMatterTlv.jar b/mobile/libs/libMatterTlv.jar
new file mode 100644
index 00000000..d8d04a31
Binary files /dev/null and b/mobile/libs/libMatterTlv.jar differ
diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml
index 1a5ef942..6d02a259 100644
--- a/mobile/src/main/AndroidManifest.xml
+++ b/mobile/src/main/AndroidManifest.xml
@@ -23,6 +23,7 @@
+
-
+
-
+
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/Parsing/DescriptorParser.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/Parsing/DescriptorParser.kt
index eab58569..c99153ab 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/Parsing/DescriptorParser.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/Parsing/DescriptorParser.kt
@@ -1,6 +1,8 @@
package com.siliconlabs.bledemo.bluetooth.parsing
import android.bluetooth.BluetoothGattDescriptor
+import android.os.Build
+import androidx.annotation.RequiresApi
import com.siliconlabs.bledemo.utils.Converters
import com.siliconlabs.bledemo.utils.StringUtils.removeWhitespaceAndCommaIfNeeded
import java.lang.StringBuilder
@@ -8,6 +10,7 @@ import java.util.*
class DescriptorParser(val descriptor: BluetoothGattDescriptor) {
+ @RequiresApi(Build.VERSION_CODES.GINGERBREAD)
fun getFormattedValue(): String {
val uuid = descriptor.uuid
val value = descriptor.value
@@ -64,7 +67,7 @@ class DescriptorParser(val descriptor: BluetoothGattDescriptor) {
}
}
- return "0x".plus(Converters.bytesToHex(value).toUpperCase(Locale.ROOT))
+ return "0x".plus(Converters.bytesToHex(value).uppercase(Locale.ROOT))
}
@@ -127,7 +130,7 @@ class DescriptorParser(val descriptor: BluetoothGattDescriptor) {
return Converters.byteToUnsignedInt(bytes[0]).toString()
}
-
+ @RequiresApi(Build.VERSION_CODES.GINGERBREAD)
private fun getReportReference(bytes: ByteArray): String {
return if (bytes.size != 2) {
return getUnknownValue(bytes)
@@ -136,14 +139,17 @@ class DescriptorParser(val descriptor: BluetoothGattDescriptor) {
val reportType = bytes[1]
val result = StringBuilder()
- result.append("Report ID: 0x").append(Converters.getHexValue(reportId).toUpperCase(Locale.ROOT)).append("\n")
- result.append("Report Type: 0x").append(Converters.getHexValue(reportType).toUpperCase(Locale.ROOT))
+ result.append("Report ID: 0x").append(Converters.getHexValue(reportId)
+ .uppercase(Locale.ROOT)).append("\n")
+ result.append("Report Type: 0x").append(Converters.getHexValue(reportType)
+ .uppercase(Locale.ROOT))
result.toString()
}
}
-
+
+ @RequiresApi(Build.VERSION_CODES.GINGERBREAD)
private fun getValidRange(bytes: ByteArray): String {
val size = bytes.size
@@ -154,20 +160,21 @@ class DescriptorParser(val descriptor: BluetoothGattDescriptor) {
result.append("Lower inclusive value: 0x")
for (i in 0 until size / 2) {
- result.append(Converters.getHexValue(bytes[i]).toUpperCase(Locale.ROOT))
+ result.append(Converters.getHexValue(bytes[i]).uppercase(Locale.ROOT))
}
result.append("\nUpper inclusive value: 0x")
for (i in size / 2 until size) {
- result.append(Converters.getHexValue(bytes[i]).toUpperCase(Locale.ROOT))
+ result.append(Converters.getHexValue(bytes[i]).uppercase(Locale.ROOT))
}
return result.toString()
}
}
+ @RequiresApi(Build.VERSION_CODES.GINGERBREAD)
private fun getUnknownValue(bytes: ByteArray): String {
- return "Unknown value: 0x".plus(Converters.bytesToHex(bytes).toUpperCase(Locale.ROOT))
+ return "Unknown value: 0x".plus(Converters.bytesToHex(bytes).uppercase(Locale.ROOT))
}
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 8537a0ae..11345fe0 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
@@ -5,9 +5,21 @@ import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
-import android.bluetooth.*
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothGatt
+import android.bluetooth.BluetoothGattCallback
+import android.bluetooth.BluetoothGattCharacteristic
+import android.bluetooth.BluetoothGattDescriptor
+import android.bluetooth.BluetoothGattServer
+import android.bluetooth.BluetoothGattServerCallback
+import android.bluetooth.BluetoothGattService
+import android.bluetooth.BluetoothManager
+import android.bluetooth.BluetoothProfile
import android.bluetooth.le.ScanCallback
-import android.bluetooth.le.ScanCallback.*
+import android.bluetooth.le.ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED
+import android.bluetooth.le.ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED
+import android.bluetooth.le.ScanCallback.SCAN_FAILED_INTERNAL_ERROR
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanSettings
import android.content.BroadcastReceiver
@@ -22,19 +34,31 @@ import android.os.Looper
import android.widget.Toast
import androidx.core.location.LocationManagerCompat
import com.siliconlabs.bledemo.R
-import com.siliconlabs.bledemo.bluetooth.ble.*
+import com.siliconlabs.bledemo.bluetooth.ble.BleScanCallback
+import com.siliconlabs.bledemo.bluetooth.ble.BluetoothDeviceInfo
+import com.siliconlabs.bledemo.bluetooth.ble.BluetoothScanCallback
+import com.siliconlabs.bledemo.bluetooth.ble.ConnectedDeviceInfo
+import com.siliconlabs.bledemo.bluetooth.ble.GattConnection
+import com.siliconlabs.bledemo.bluetooth.ble.ScanResultCompat
+import com.siliconlabs.bledemo.bluetooth.ble.TimeoutGattCallback
import com.siliconlabs.bledemo.features.configure.advertiser.activities.PendingServerConnectionActivity
import com.siliconlabs.bledemo.features.configure.advertiser.services.AdvertiserService
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.BluetoothGattServicesCreator
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.GattConfiguratorStorage
-import com.siliconlabs.bledemo.features.scan.browser.models.logs.*
+import com.siliconlabs.bledemo.features.scan.browser.models.logs.ConnectionStateChangeLog
+import com.siliconlabs.bledemo.features.scan.browser.models.logs.GattOperationLog
+import com.siliconlabs.bledemo.features.scan.browser.models.logs.GattOperationWithDataLog
+import com.siliconlabs.bledemo.features.scan.browser.models.logs.GattOperationWithParameterLog
+import com.siliconlabs.bledemo.features.scan.browser.models.logs.Log
+import com.siliconlabs.bledemo.features.scan.browser.models.logs.TimeoutLog
import com.siliconlabs.bledemo.home_screen.activities.MainActivity
import com.siliconlabs.bledemo.utils.LocalService
import com.siliconlabs.bledemo.utils.Notifications
import com.siliconlabs.bledemo.utils.UuidConsts
import timber.log.Timber
import java.lang.reflect.Method
-import java.util.*
+import java.util.LinkedList
+import java.util.UUID
/**
* Service handling Bluetooth (regular and BLE) communications.
@@ -81,7 +105,8 @@ class BluetoothService : LocalService() {
ESL_DEMO,
MATTER_DEMO,
WIFI_OTA_UPDATE,
- DEV_KIT_SENSOR
+ DEV_KIT_SENSOR,
+ WIFI_THROUGHPUT_TEST
}
interface ScanListener {
@@ -211,6 +236,7 @@ class BluetoothService : LocalService() {
interface ServicesStateListener {
fun onBluetoothStateChanged(isOn: Boolean)
fun onLocationStateChanged(isOn: Boolean)
+ fun onNotificationStateChanged(isOn: Boolean)
}
private val bluetoothReceiver: BroadcastReceiver = object : BroadcastReceiver() {
@@ -251,6 +277,10 @@ class BluetoothService : LocalService() {
return LocationManagerCompat.isLocationEnabled(locationManager)
}
+ fun areNotificationOn() : Boolean {
+ return (getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).areNotificationsEnabled()
+ }
+
fun initGattServer() {
if (bluetoothGattServer == null && bluetoothAdapter?.isEnabled == true && areBluetoothPermissionsEnabled) {
bluetoothGattServer = bluetoothManager.openGattServer(this, bluetoothGattServerCallback)
@@ -858,7 +888,7 @@ class BluetoothService : LocalService() {
.setContentTitle(getString(R.string.notification_title_device_has_connected, deviceName))
.setContentText(getString(R.string.notification_note_debug_connection))
.addAction(buildAction(getString(R.string.button_yes), getYesPendingIntent(device)))
- .addAction(buildAction(getString(R.string.notification_button_yes_and_open), getYesAndOpenPendingIntent(device)))
+ /* .addAction(buildAction(getString(R.string.notification_button_yes_and_open), getYesAndOpenPendingIntent(device)))*/
.addAction(buildAction(getString(R.string.button_no), getNoPendingIntent()))
.build()
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/beacon_utils/BleFormat.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/beacon_utils/BleFormat.kt
index f39141d4..a195ed13 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/beacon_utils/BleFormat.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/beacon_utils/BleFormat.kt
@@ -2,6 +2,7 @@ package com.siliconlabs.bledemo.bluetooth.beacon_utils
import com.siliconlabs.bledemo.bluetooth.ble.BluetoothDeviceInfo
import com.siliconlabs.bledemo.R
+import java.util.Locale
enum class BleFormat(val nameResId: Int, val iconResId: Int) {
UNSPECIFIED(R.string.unspecified, R.drawable.ic_beacon_immediate),
@@ -66,7 +67,7 @@ enum class BleFormat(val nameResId: Int, val iconResId: Int) {
val uuidList = deviceInfo.scanInfo?.scanRecord?.serviceUuids
if (uuidList != null && !uuidList.isEmpty()) {
for (parcelUuid in uuidList) {
- val parcelString = parcelUuid.toString().substring(4, 8).toLowerCase()
+ val parcelString = parcelUuid.toString().substring(4, 8).lowercase(Locale.US)
if (EDDYSTONE_SERVICE_UUID == parcelString) {
return true
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/beacon_utils/eddystone/Beacon.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/beacon_utils/eddystone/Beacon.kt
index 6c7d38f8..f97022f3 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/beacon_utils/eddystone/Beacon.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/beacon_utils/eddystone/Beacon.kt
@@ -1,5 +1,7 @@
package com.siliconlabs.bledemo.bluetooth.beacon_utils.eddystone
+import java.util.Locale
+
// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -147,11 +149,11 @@ class Beacon(private val deviceAddress: String, var rssi: Int) {
*/
operator fun contains(s: String?): Boolean {
return (s == null || s.isEmpty()
- || deviceAddress.replace(":", "").toLowerCase().contains(s.toLowerCase())
+ || deviceAddress.replace(":", "").lowercase().contains(s.lowercase(Locale.US))
|| (uidStatus.uidValue != null
- && uidStatus.uidValue?.toLowerCase()?.contains(s.toLowerCase())!!)
+ && uidStatus.uidValue?.lowercase()?.contains(s.lowercase(Locale.US))!!)
|| (urlStatus.urlValue != null
- && urlStatus.urlValue?.toLowerCase()?.contains(s.toLowerCase())!!))
+ && urlStatus.urlValue?.lowercase()?.contains(s.lowercase(Locale.US))!!))
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/Converters.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/Converters.kt
index f4c2e4de..012fb212 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/Converters.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/Converters.kt
@@ -256,7 +256,7 @@ object Converters {
}
// prepend the sign up to 64 bits
- var result = ""
+ var result:String
val stringPrependExtendSign = StringBuilder(binaryString)
for (i in 0 until 64 - binaryString.length) {
stringPrependExtendSign.insert(0, binaryString.substring(0, 1))
@@ -357,7 +357,7 @@ object Converters {
val minExponent = -8
try {
- var mantissa = 0
+ var mantissa:Int
var exponent = 0
if (input.contains('.')) {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/FilterDeviceParams.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/FilterDeviceParams.kt
index de9b542f..2ae7f75e 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/FilterDeviceParams.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/FilterDeviceParams.kt
@@ -3,7 +3,7 @@ package com.siliconlabs.bledemo.utils
import android.content.Context
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.bluetooth.beacon_utils.BleFormat
-import kotlinx.android.synthetic.main.fragment_filter.*
+
data class FilterDeviceParams(
val name: String?,
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/RemovalDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/RemovalDialog.kt
index d460f1d5..1f145abd 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/RemovalDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/RemovalDialog.kt
@@ -5,35 +5,40 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes
+import by.kirich1409.viewbindingdelegate.viewBinding
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
-import kotlinx.android.synthetic.main.dialog_info_ok_cancel.view.*
+import com.siliconlabs.bledemo.databinding.DialogInfoOkCancelBinding
+
abstract class RemovalDialog(
@StringRes private val nameRes: Int,
private val onOkClicked: () -> Unit
) : BaseDialogFragment() {
-
+ // private val binding by viewBinding(DialogInfoOkCancelBinding::bind)
+ private lateinit var binding: DialogInfoOkCancelBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ): View = inflater
- .inflate(R.layout.dialog_info_ok_cancel, container, false)
- .apply {
- val name = context.getString(nameRes)
- tv_dialog_title.text = context.getString(R.string.dialog_title_remove, name)
- tv_dialog_content.text = context.getString(R.string.dialog_description_remove, name)
+ ): View {
+ binding = DialogInfoOkCancelBinding.inflate(inflater, container, false).apply {
+ val name = context?.getString(nameRes)
+ tvDialogTitle.text = context?.getString(R.string.dialog_title_remove, name)
+ tvDialogContent.text =
+ context?.getString(R.string.dialog_description_remove, name)
- btn_ok.setOnClickListener {
- if (cb_dont_show_again.isChecked) {
+ btnOk.setOnClickListener {
+ if (binding.cbDontShowAgain.isChecked) {
blockDisplayingRemovalDialog()
}
onOkClicked()
dismiss()
}
- btn_cancel.setOnClickListener { dismiss() }
+ btnCancel.setOnClickListener { dismiss() }
}
+ return binding.root
+ }
abstract fun blockDisplayingRemovalDialog()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/UuidUtils.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/UuidUtils.kt
index dd97246b..024e7304 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/UuidUtils.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/UuidUtils.kt
@@ -14,7 +14,7 @@ object UuidUtils {
}
fun getUuidText(uuid: UUID): String {
- val strUuid = uuid.toString().toUpperCase(Locale.getDefault())
+ val strUuid = uuid.toString().uppercase(Locale.getDefault())
return if (isSig(strUuid)) {
"0x" + convert128to16UUID(strUuid)
} else {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/common/views/DetailsRow.kt b/mobile/src/main/java/com/siliconlabs/bledemo/common/views/DetailsRow.kt
index a6aa148e..b3472223 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/common/views/DetailsRow.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/common/views/DetailsRow.kt
@@ -4,17 +4,24 @@ import android.content.Context
import android.view.LayoutInflater
import android.widget.LinearLayout
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.list_item_details_row.view.*
+import com.siliconlabs.bledemo.databinding.ListItemDetailsRowBinding
+
+//import kotlinx.android.synthetic.main.list_item_details_row.view.*
class DetailsRow : LinearLayout {
+ lateinit var binding: ListItemDetailsRowBinding
init {
- LayoutInflater.from(context).inflate(R.layout.list_item_details_row, this)
+ // LayoutInflater.from(context).inflate(R.layout.list_item_details_row, this)
+ binding = ListItemDetailsRowBinding.inflate(LayoutInflater.from(context))
+
}
constructor(context: Context) : super(context)
constructor(context: Context, title: String?, text: String?) : super(context) {
- tv_title.text = title
- tv_details.text = text
+// tv_title.text = title
+// tv_details.text = text
+ binding.tvDetails.text = text
+ binding.tvTitle.text = title
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/activities/AdvertiserConfigActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/activities/AdvertiserConfigActivity.kt
index d5986aae..4b01bfe6 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/activities/AdvertiserConfigActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/activities/AdvertiserConfigActivity.kt
@@ -12,31 +12,43 @@ import android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
import android.text.TextWatcher
import android.text.style.RelativeSizeSpan
import android.util.TypedValue
-import android.view.*
+import android.view.LayoutInflater
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
-import android.widget.LinearLayout
import android.widget.Spinner
import androidx.constraintlayout.widget.ConstraintLayout
+import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.base.activities.BaseActivity
+import com.siliconlabs.bledemo.databinding.ActivityAdvertiserConfigBinding
+import com.siliconlabs.bledemo.databinding.AdvertiserDataContainerBinding
+import com.siliconlabs.bledemo.databinding.DataTypeItemBinding
+import com.siliconlabs.bledemo.databinding.DataTypeLayoutBinding
import com.siliconlabs.bledemo.features.configure.advertiser.adapters.DataTypeAdapter
+import com.siliconlabs.bledemo.features.configure.advertiser.dialogs.LeaveAdvertiserConfigDialog
+import com.siliconlabs.bledemo.features.configure.advertiser.dialogs.ManufacturerDataDialog
+import com.siliconlabs.bledemo.features.configure.advertiser.dialogs.RemoveServicesDialog
+import com.siliconlabs.bledemo.features.configure.advertiser.dialogs.Service128BitDataDialog
+import com.siliconlabs.bledemo.features.configure.advertiser.dialogs.Service16BitDataDialog
+import com.siliconlabs.bledemo.features.configure.advertiser.enums.AdvertisingMode
+import com.siliconlabs.bledemo.features.configure.advertiser.enums.DataMode
+import com.siliconlabs.bledemo.features.configure.advertiser.enums.DataType
+import com.siliconlabs.bledemo.features.configure.advertiser.enums.LimitType
+import com.siliconlabs.bledemo.features.configure.advertiser.enums.Phy
+import com.siliconlabs.bledemo.features.configure.advertiser.models.AdvertiserData
+import com.siliconlabs.bledemo.features.configure.advertiser.models.DataPacket
+import com.siliconlabs.bledemo.features.configure.advertiser.models.ExtendedSettings
+import com.siliconlabs.bledemo.features.configure.advertiser.models.Manufacturer
+import com.siliconlabs.bledemo.features.configure.advertiser.models.Service128Bit
+import com.siliconlabs.bledemo.features.configure.advertiser.models.Service16Bit
import com.siliconlabs.bledemo.features.configure.advertiser.presenters.AdvertiserConfigActivityPresenter
import com.siliconlabs.bledemo.features.configure.advertiser.utils.AdvertiserStorage
import com.siliconlabs.bledemo.features.configure.advertiser.utils.Translator
import com.siliconlabs.bledemo.features.configure.advertiser.utils.Validator
-import com.siliconlabs.bledemo.base.activities.BaseActivity
-import com.siliconlabs.bledemo.R
-import com.siliconlabs.bledemo.features.configure.advertiser.dialogs.*
-import com.siliconlabs.bledemo.features.configure.advertiser.enums.*
-import com.siliconlabs.bledemo.features.configure.advertiser.models.*
-import kotlinx.android.synthetic.main.advertiser_config_data.*
-import kotlinx.android.synthetic.main.advertiser_config_name.*
-import kotlinx.android.synthetic.main.advertiser_config_parameters.*
-import kotlinx.android.synthetic.main.advertiser_config_type.*
-import kotlinx.android.synthetic.main.advertiser_data_container.view.*
-import kotlinx.android.synthetic.main.data_type_item.view.*
-import kotlinx.android.synthetic.main.data_type_layout.*
-import kotlinx.android.synthetic.main.data_type_layout.view.*
-import kotlinx.android.synthetic.main.data_type_layout.view.ib_remove
+
class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
private lateinit var presenter: AdvertiserConfigActivityPresenter
@@ -48,6 +60,7 @@ class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
private var spLegacyInitialSetup = true
private var spExtendedInitialSetup = true
+ private lateinit var binding: ActivityAdvertiserConfigBinding
companion object {
const val EXTRA_ADVERTISER_ITEM = "EXTRA_ADVERTISER_ITEM"
@@ -56,18 +69,26 @@ class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_advertiser_config)
+ binding = ActivityAdvertiserConfigBinding.inflate(LayoutInflater.from(this))
+ setContentView(binding.root)
prepareToolbar()
resetInitialSetupFlags()
- presenter = AdvertiserConfigActivityPresenter(this, AdvertiserStorage(this@AdvertiserConfigActivity))
+ presenter = AdvertiserConfigActivityPresenter(
+ this,
+ AdvertiserStorage(this@AdvertiserConfigActivity)
+ )
presenter.prepareAdvertisingTypes()
presenter.preparePhyParameters()
- advertiserData = intent.extras?.getParcelable(EXTRA_ADVERTISER_ITEM) as AdvertiserData
+ advertiserData =
+ intent.extras?.getParcelable(EXTRA_ADVERTISER_ITEM) as AdvertiserData
position = intent.getIntExtra(EXTRA_ITEM_POSITION, 0)
- presenter.onItemReceived(advertiserData, AdvertiserStorage(this@AdvertiserConfigActivity).isAdvertisingExtensionSupported())
+ presenter.onItemReceived(
+ advertiserData,
+ AdvertiserStorage(this@AdvertiserConfigActivity).isAdvertisingExtensionSupported()
+ )
startConfigData = advertiserData.deepCopy()
@@ -94,15 +115,18 @@ class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
presenter.handleSave()
true
}
+
android.R.id.home -> {
exitConfigView()
true
}
+
else -> super.onOptionsItemSelected(item)
}
}
override fun onBackPressed() {
+ super.onBackPressed()
exitConfigView()
}
@@ -142,15 +166,16 @@ class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
// 3. Verify if other data has changed
startConfigData.apply {
when {
- name != et_advertising_set_name.text.toString() -> return true
- isLegacy != rb_legacy_advertising.isChecked -> return true
+
+ name != binding.advConfigName.etAdvertisingSetName.text.toString() -> return true
+ isLegacy != binding.advConfigType.rbLegacyAdvertising.isChecked -> return true
mode != getAdvertisingMode() -> return true
settings != getExtendedSettings() -> return true
advertisingIntervalMs != getAdvertisingInterval() -> return true
txPower != getTxPower() -> return true
limitType != getAdvertisingLimitType() -> return true
- timeLimit.toString() != et_time_limit.text.toString() -> return true
- isEventLimitAvailable() && eventLimit.toString() != et_event_limit.text.toString() -> return true
+ timeLimit.toString() != binding.advConfigParam.etTimeLimit.text.toString() -> return true
+ isEventLimitAvailable() && eventLimit.toString() != binding.advConfigParam.etEventLimit.text.toString() -> return true
}
}
@@ -160,7 +185,7 @@ class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
private fun handleAdvertisingSetNameChanges() {
- et_advertising_set_name.addTextChangedListener(object : TextWatcher {
+ binding.advConfigName.etAdvertisingSetName.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
@@ -170,23 +195,32 @@ class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
}
private fun isEventLimitAvailable(): Boolean {
- return ll_event_limit.visibility == View.VISIBLE
+ return binding.advConfigParam.llEventLimit.visibility == View.VISIBLE
}
private fun isTxPowerNotValid(): Boolean {
- return ll_tx_power.visibility == View.VISIBLE && !Validator.isTxPowerValid(et_tx_power.text.toString())
+
+ return binding.advConfigParam.llTxPower.visibility == View.VISIBLE &&
+ !Validator.isTxPowerValid(binding.advConfigParam.etTxPower.text.toString())
}
private fun isAdvertisingIntervalNotValid(): Boolean {
- return ll_advertising_interval.visibility == View.VISIBLE && !Validator.isAdvertisingIntervalValid(et_advertising_interval.text.toString())
+ return binding.advConfigParam.llAdvertisingInterval.visibility == View.VISIBLE &&
+ !Validator.isAdvertisingIntervalValid(
+ binding.advConfigParam.etAdvertisingInterval.text.toString()
+ )
}
private fun isTimeLimitNotValid(): Boolean {
- return rb_time_limit.isChecked && !Validator.isAdvertisingTimeLimitValid(et_time_limit.text.toString(), true)
+ return binding.advConfigParam.rbTimeLimit.isChecked && !Validator.isAdvertisingTimeLimitValid(
+ binding.advConfigParam.etTimeLimit.text.toString(),
+ true
+ )
}
private fun isEventLimitNotValid(): Boolean {
- return rb_event_limit.isChecked && !Validator.isAdvertisingEventLimitValid(et_event_limit.text.toString())
+ return binding.advConfigParam.rbEventLimit.isChecked &&
+ !Validator.isAdvertisingEventLimitValid(binding.advConfigParam.etEventLimit.text.toString())
}
private fun isAnyInputNotValid(): Boolean {
@@ -203,8 +237,8 @@ class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
else if (isEventLimitNotValid())
showMessage(R.string.advertiser_config_message_invalid_event_limit)
else {
- val name = et_advertising_set_name.text.toString()
- val isLegacy = rb_legacy_advertising.isChecked
+ val name = binding.advConfigName.etAdvertisingSetName.text.toString()
+ val isLegacy = binding.advConfigType.rbLegacyAdvertising.isChecked
val advertisingMode = getAdvertisingMode()
val settings = getExtendedSettings()
val interval = getAdvertisingInterval()
@@ -228,502 +262,777 @@ class AdvertiserConfigActivity : BaseActivity(), IAdvertiserConfigActivityView {
}
private fun getAdvertisingInterval(): Int {
- return et_advertising_interval.text.toString().toInt()
+ return binding.advConfigParam.etAdvertisingInterval.text.toString().toInt()
}
private fun getTxPower(): Int {
- return et_tx_power.text.toString().toInt()
+ return binding.advConfigParam.etTxPower.text.toString().toInt()
}
private fun getAdvertisingLimitType(): LimitType {
return when {
- rb_no_limit.isChecked -> LimitType.NO_LIMIT
- rb_time_limit.isChecked -> LimitType.TIME_LIMIT
+ binding.advConfigParam.rbNoLimit.isChecked -> LimitType.NO_LIMIT
+ binding.advConfigParam.rbTimeLimit.isChecked -> LimitType.TIME_LIMIT
else -> LimitType.EVENT_LIMIT
}
}
private fun getAdvertisingTimeLimit(): Int {
- return if (rb_time_limit.isChecked) et_time_limit.text.toString().toInt()
+ return if (binding.advConfigParam.rbTimeLimit.isChecked) binding.advConfigParam.etTimeLimit.text.toString()
+ .toInt()
else -1
}
private fun getAdvertisingEventLimit(): Int {
- return if (rb_event_limit.isChecked) et_event_limit.text.toString().toInt()
+ return if (binding.advConfigParam.rbEventLimit.isChecked) binding.advConfigParam.etEventLimit.text.toString()
+ .toInt()
else -1
}
private fun getAdvertisingMode(): AdvertisingMode {
- return if (rb_legacy_advertising.isChecked) translator.getStringAsAdvertisingMode(sp_legacy.selectedItem.toString())
- else translator.getStringAsAdvertisingMode(sp_extended.selectedItem.toString())
+
+ return if (binding.advConfigType.rbLegacyAdvertising.isChecked) translator.getStringAsAdvertisingMode(
+ binding.advConfigType.spLegacy.selectedItem.toString()
+ )
+ else translator
+ .getStringAsAdvertisingMode(binding.advConfigType.spExtended.selectedItem.toString())
}
private fun getExtendedSettings(): ExtendedSettings {
- return if (sp_primary_phy.isEnabled) {
- val primaryPhy = translator.getStringAsPhy(sp_primary_phy.selectedItem.toString())
- val secondaryPhy: Phy = translator.getStringAsPhy(sp_secondary_phy.selectedItem.toString())
- ExtendedSettings(cb_include_tx_power.isChecked, cb_anonymous.isChecked, primaryPhy, secondaryPhy)
- } else ExtendedSettings(cb_include_tx_power.isChecked, cb_anonymous.isChecked, null, null)
+
+ return if (binding.advConfigParam.spPrimaryPhy.isEnabled) {
+ val primaryPhy =
+ translator.getStringAsPhy(binding.advConfigParam.spPrimaryPhy.selectedItem.toString())
+ val secondaryPhy: Phy =
+ translator.getStringAsPhy(binding.advConfigParam.spSecondaryPhy.selectedItem.toString())
+ ExtendedSettings(
+ binding.advConfigType.cbIncludeTxPower.isChecked,
+ binding.advConfigType.cbAnonymous.isChecked,
+ primaryPhy,
+ secondaryPhy
+ )
+ } else ExtendedSettings(
+ binding.advConfigType.cbIncludeTxPower.isChecked,
+ binding.advConfigType.cbAnonymous.isChecked,
+ null,
+ null
+ )
}
private fun handleAdvertisingLimitSelection() {
- rb_no_limit.setOnClickListener {
- rb_no_limit.isChecked = true
+ binding.advConfigParam.rbNoLimit.setOnClickListener {
+ binding.advConfigParam.rbNoLimit.isChecked = true
setTimeLimitState(false)
setEventLimitState(false)
}
- rb_time_limit.setOnClickListener {
- rb_no_limit.isChecked = false
+ binding.advConfigParam.rbTimeLimit.setOnClickListener {
+ binding.advConfigParam.rbNoLimit.isChecked = false
setTimeLimitState(true)
setEventLimitState(false)
}
- rb_event_limit.setOnClickListener {
- rb_no_limit.isChecked = false
+ binding.advConfigParam.rbEventLimit.setOnClickListener {
+ binding.advConfigParam.rbNoLimit.isChecked = false
setTimeLimitState(false)
setEventLimitState(true)
}
}
private fun setTimeLimitState(enabled: Boolean) {
- rb_time_limit.isChecked = enabled
- et_time_limit.isEnabled = enabled
+ binding.advConfigParam.rbTimeLimit.isChecked = enabled
+ binding.advConfigParam.etTimeLimit.isEnabled = enabled
}
private fun setEventLimitState(enabled: Boolean) {
- rb_event_limit.isChecked = enabled
- et_event_limit.isEnabled = enabled
+ binding.advConfigParam.rbEventLimit.isChecked = enabled
+ binding.advConfigParam.etEventLimit.isEnabled = enabled
}
- private fun updateAdvertisingLimitLabels(){
- rb_time_limit.text = buildLabelWithResizedHint(getString(R.string.advertiser_label_time_limit))
- rb_event_limit.text = buildLabelWithResizedHint(getString(R.string.advertiser_label_event_limit))
+ private fun updateAdvertisingLimitLabels() {
+ binding.advConfigParam.rbTimeLimit.text =
+ buildLabelWithResizedHint(getString(R.string.advertiser_label_time_limit))
+ binding.advConfigParam.rbEventLimit.text =
+ buildLabelWithResizedHint(getString(R.string.advertiser_label_event_limit))
}
private fun buildLabelWithResizedHint(labelText: String): SpannableString {
val linebreakIndex = labelText.indexOf('\n')
val label = SpannableString(labelText)
if (linebreakIndex > -1) {
- label.setSpan(RelativeSizeSpan(12f/14f), linebreakIndex + 1, labelText.length, SPAN_EXCLUSIVE_EXCLUSIVE)
+ label.setSpan(
+ RelativeSizeSpan(12f / 14f),
+ linebreakIndex + 1,
+ labelText.length,
+ SPAN_EXCLUSIVE_EXCLUSIVE
+ )
}
return label
}
- override fun onAdvertisingTypesPrepared(isLegacy: Boolean, legacyModes: List, extendedModes: List) {
- val legacyAdapter = ArrayAdapter(this, R.layout.spinner_item_layout_medium, translator.getValuesAsStringList(legacyModes))
+ override fun onAdvertisingTypesPrepared(
+ isLegacy: Boolean,
+ legacyModes: List,
+ extendedModes: List
+ ) {
+ val legacyAdapter = ArrayAdapter(
+ this,
+ R.layout.spinner_item_layout_medium,
+ translator.getValuesAsStringList(legacyModes)
+ )
+
legacyAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item_layout)
- sp_legacy.adapter = legacyAdapter
+ binding.advConfigType.spLegacy.adapter = legacyAdapter
- val extendedAdapter = ArrayAdapter(this, R.layout.spinner_item_layout_medium, translator.getValuesAsStringList(extendedModes))
+ val extendedAdapter = ArrayAdapter(
+ this,
+ R.layout.spinner_item_layout_medium,
+ translator.getValuesAsStringList(extendedModes)
+ )
extendedAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item_layout)
- sp_extended.adapter = extendedAdapter
+ binding.advConfigType.spExtended.adapter = extendedAdapter
- if (isLegacy) tv_extended_adv_not_supported.visibility = View.VISIBLE
- sp_extended.isEnabled = false
- cb_anonymous.isEnabled = false
- cb_include_tx_power.isEnabled = false
- rb_extended_advertising.isEnabled = !isLegacy
- sp_primary_phy.isEnabled = false
- sp_secondary_phy.isEnabled = false
+ if (isLegacy) binding.advConfigType.tvExtendedAdvNotSupported.visibility = View.VISIBLE
+ binding.advConfigType.spExtended.isEnabled = false
+ binding.advConfigType.cbAnonymous.isEnabled = false
+ binding.advConfigType.cbIncludeTxPower.isEnabled = false
+ binding.advConfigType.rbExtendedAdvertising.isEnabled = !isLegacy
+ binding.advConfigParam.spPrimaryPhy.isEnabled = false
+ binding.advConfigParam.spSecondaryPhy.isEnabled = false
if (!isLegacy) {
- rb_extended_advertising.setOnCheckedChangeListener { _, isChecked ->
+ binding.advConfigType.rbExtendedAdvertising.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
- cb_anonymous.isEnabled = sp_extended.selectedItem.toString() == getString(R.string.advertiser_mode_non_connectable_non_scannable)
- rb_legacy_advertising.isChecked = false
- sp_legacy.isEnabled = false
- sp_legacy.visibility = View.GONE
- sp_extended.isEnabled = true
- sp_extended.visibility = View.VISIBLE
- cb_include_tx_power.isEnabled = true
- sp_primary_phy.isEnabled = true
- sp_secondary_phy.isEnabled = true
-
- presenter.setSupportedData(false, translator.getStringAsAdvertisingMode(sp_extended.selectedItem.toString()))
+ binding.advConfigType.cbAnonymous.isEnabled =
+ binding.advConfigType.spExtended.selectedItem.toString() == getString(R.string.advertiser_mode_non_connectable_non_scannable)
+ binding.advConfigType.rbLegacyAdvertising.isChecked = false
+ binding.advConfigType.spLegacy.isEnabled = false
+ binding.advConfigType.spLegacy.visibility = View.GONE
+ binding.advConfigType.spExtended.isEnabled = true
+ binding.advConfigType.spExtended.visibility = View.VISIBLE
+ binding.advConfigType.cbIncludeTxPower.isEnabled = true
+ binding.advConfigParam.spPrimaryPhy.isEnabled = true
+ binding.advConfigParam.spSecondaryPhy.isEnabled = true
+
+ presenter.setSupportedData(
+ false,
+ translator.getStringAsAdvertisingMode(binding.advConfigType.spExtended.selectedItem.toString())
+ )
}
}
- sp_extended.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
- override fun onNothingSelected(parent: AdapterView<*>?) {}
- override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
- if (!spExtendedInitialSetup) {
- if (sp_extended.selectedItem.toString() == getString(R.string.advertiser_mode_non_connectable_non_scannable)) {
- cb_anonymous.isEnabled = true
+ binding.advConfigType.spExtended.onItemSelectedListener =
+ object : AdapterView.OnItemSelectedListener {
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (!spExtendedInitialSetup) {
+ if (binding.advConfigType.spExtended.selectedItem.toString() == getString(
+ R.string.advertiser_mode_non_connectable_non_scannable
+ )
+ ) {
+ binding.advConfigType.cbAnonymous.isEnabled = true
+ } else {
+ binding.advConfigType.cbAnonymous.isEnabled = false
+ binding.advConfigType.cbAnonymous.isChecked = false
+ }
+ presenter.setSupportedData(
+ false,
+ translator.getStringAsAdvertisingMode(binding.advConfigType.spExtended.selectedItem.toString())
+ )
} else {
- cb_anonymous.isEnabled = false
- cb_anonymous.isChecked = false
+ spExtendedInitialSetup = false
}
- presenter.setSupportedData(false, translator.getStringAsAdvertisingMode(sp_extended.selectedItem.toString()))
- } else {
- spExtendedInitialSetup = false
}
}
- }
}
- rb_legacy_advertising.setOnCheckedChangeListener { _, isChecked ->
+ binding.advConfigType.rbLegacyAdvertising.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
- rb_extended_advertising.isChecked = false
- sp_legacy.isEnabled = true
- sp_legacy.visibility = View.VISIBLE
- sp_extended.isEnabled = false
- sp_extended.visibility = View.GONE
- cb_anonymous.isEnabled = false
- cb_include_tx_power.isEnabled = false
- sp_primary_phy.isEnabled = false
- sp_secondary_phy.isEnabled = false
- cb_include_tx_power.isChecked = false
- cb_anonymous.isChecked = false
-
- presenter.setSupportedData(true, translator.getStringAsAdvertisingMode(sp_legacy.selectedItem.toString()))
+ binding.advConfigType.rbExtendedAdvertising.isChecked = false
+ binding.advConfigType.spLegacy.isEnabled = true
+ binding.advConfigType.spLegacy.visibility = View.VISIBLE
+ binding.advConfigType.spExtended.isEnabled = false
+ binding.advConfigType.spExtended.visibility = View.GONE
+ binding.advConfigType.cbAnonymous.isEnabled = false
+ binding.advConfigType.cbIncludeTxPower.isEnabled = false
+ binding.advConfigParam.spPrimaryPhy.isEnabled = false
+ binding.advConfigParam.spSecondaryPhy.isEnabled = false
+ binding.advConfigType.cbIncludeTxPower.isChecked = false
+ binding.advConfigType.cbAnonymous.isChecked = false
+
+ presenter.setSupportedData(
+ true,
+ translator.getStringAsAdvertisingMode(binding.advConfigType.spLegacy.selectedItem.toString())
+ )
}
}
- sp_legacy.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
- override fun onNothingSelected(parent: AdapterView<*>?) {}
- override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
- if (!spLegacyInitialSetup) {
- presenter.setSupportedData(true, translator.getStringAsAdvertisingMode(sp_legacy.selectedItem.toString()))
- } else {
- spLegacyInitialSetup = false
+ binding.advConfigType.spLegacy.onItemSelectedListener =
+ object : AdapterView.OnItemSelectedListener {
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (!spLegacyInitialSetup) {
+ presenter.setSupportedData(
+ true,
+ translator.getStringAsAdvertisingMode(binding.advConfigType.spLegacy.selectedItem.toString())
+ )
+ } else {
+ spLegacyInitialSetup = false
+ }
}
}
- }
}
- override fun onAdvertisingParametersPrepared(isLegacy: Boolean, primaryPhys: List, secondaryPhys: List) {
- val primaryPhyAdapter = ArrayAdapter(this, R.layout.spinner_item_layout_medium, translator.getValuesAsStringList(primaryPhys))
+ override fun onAdvertisingParametersPrepared(
+ isLegacy: Boolean,
+ primaryPhys: List,
+ secondaryPhys: List
+ ) {
+ binding.advConfigType
+ val primaryPhyAdapter = ArrayAdapter(
+ this,
+ R.layout.spinner_item_layout_medium,
+ translator.getValuesAsStringList(primaryPhys)
+ )
primaryPhyAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item_layout)
- sp_primary_phy.adapter = primaryPhyAdapter
+ binding.advConfigParam.spPrimaryPhy.adapter = primaryPhyAdapter
- val secondaryPhyAdapter = ArrayAdapter(this, R.layout.spinner_item_layout_medium, translator.getValuesAsStringList(secondaryPhys))
+ val secondaryPhyAdapter = ArrayAdapter(
+ this,
+ R.layout.spinner_item_layout_medium,
+ translator.getValuesAsStringList(secondaryPhys)
+ )
secondaryPhyAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item_layout)
- sp_secondary_phy.adapter = secondaryPhyAdapter
+ binding.advConfigParam.spSecondaryPhy.adapter = secondaryPhyAdapter
}
override fun onSupportedDataPrepared(isAdvertisingData: Boolean, isScanRespData: Boolean) {
- btn_add_advertising_data.isEnabled = isAdvertisingData
- tv_adv_data_available_bytes.visibility = if (isAdvertisingData) View.VISIBLE else View.GONE
- ll_data_advertising_data.visibility = if (isAdvertisingData) View.VISIBLE else View.GONE
- btn_add_scan_response_data.isEnabled = isScanRespData
- tv_scan_resp_available_bytes.visibility = if (isScanRespData) View.VISIBLE else View.GONE
- ll_data_scan_resp_data.visibility = if (isScanRespData) View.VISIBLE else View.GONE
+
+ binding.advConfigData.btnAddAdvertisingData.isEnabled = isAdvertisingData
+ binding.advConfigData.tvAdvDataAvailableBytes.visibility =
+ if (isAdvertisingData) View.VISIBLE else View.GONE
+ binding.advConfigData.llDataAdvertisingData.root.visibility =
+ if (isAdvertisingData) View.VISIBLE else View.GONE
+ binding.advConfigData.btnAddScanResponseData.isEnabled = isScanRespData
+ binding.advConfigData.tvScanRespAvailableBytes.visibility =
+ if (isScanRespData) View.VISIBLE else View.GONE
+ binding.advConfigData.llDataScanRespData.root.visibility =
+ if (isScanRespData) View.VISIBLE else View.GONE
}
override fun populateUi(data: AdvertiserData, isAdvertisingEventSupported: Boolean) {
- et_advertising_set_name.setText(data.name)
+ binding.advConfigName.etAdvertisingSetName.setText(data.name)
title = data.name
data.isLegacy.let {
- if (data.isLegacy) setSpinnerSelection(data.mode, sp_legacy)
- else setSpinnerSelection(data.mode, sp_extended)
- rb_legacy_advertising.isChecked = data.isLegacy
- rb_extended_advertising.isChecked = !data.isLegacy
+ if (data.isLegacy) setSpinnerSelection(data.mode, binding.advConfigType.spLegacy)
+ else setSpinnerSelection(data.mode, binding.advConfigType.spExtended)
+ binding.advConfigType.rbLegacyAdvertising.isChecked = data.isLegacy
+ binding.advConfigType.rbExtendedAdvertising.isChecked = !data.isLegacy
}
data.settings.let {
- cb_include_tx_power.isChecked = data.settings.includeTxPower
- cb_anonymous.isChecked = data.settings.anonymous
- setSpinnerSelection(data.settings.primaryPhy, sp_primary_phy)
- setSpinnerSelection(data.settings.secondaryPhy, sp_secondary_phy)
+ binding.advConfigType.cbIncludeTxPower.isChecked = data.settings.includeTxPower
+ binding.advConfigType.cbAnonymous.isChecked = data.settings.anonymous
+ setSpinnerSelection(data.settings.primaryPhy, binding.advConfigParam.spPrimaryPhy)
+ setSpinnerSelection(data.settings.secondaryPhy, binding.advConfigParam.spSecondaryPhy)
}
- et_advertising_interval.setText(data.advertisingIntervalMs.toString())
- et_tx_power.setText(data.txPower.toString())
+ binding.advConfigParam.etAdvertisingInterval.setText(data.advertisingIntervalMs.toString())
+ binding.advConfigParam.etTxPower.setText(data.txPower.toString())
- rb_time_limit.text = getString(R.string.advertiser_label_time_limit)
+ binding.advConfigParam.rbTimeLimit.text = getString(R.string.advertiser_label_time_limit)
- rb_no_limit.isChecked = data.limitType == LimitType.NO_LIMIT
+ binding.advConfigParam.rbNoLimit.isChecked = data.limitType == LimitType.NO_LIMIT
setTimeLimitState(data.limitType == LimitType.TIME_LIMIT)
setEventLimitState(data.limitType == LimitType.EVENT_LIMIT)
- et_time_limit.setText(data.timeLimit.toString())
+ binding.advConfigParam.etTimeLimit.setText(data.timeLimit.toString())
- if (isAdvertisingEventSupported) et_event_limit.setText(data.eventLimit.toString())
- else ll_event_limit.visibility = View.GONE
+ if (isAdvertisingEventSupported) binding.advConfigParam.etEventLimit.setText(data.eventLimit.toString())
+ else binding.advConfigParam.llEventLimit.visibility = View.GONE
}
private fun setSpinnerSelection(selection: Any?, spinner: Spinner) {
- for (i in 0 until spinner.adapter.count) if (spinner.getItemAtPosition(i) == translator.getString(selection)) {
- spinner.setSelection(i); break
- }
+ for (i in 0 until spinner.adapter.count)
+ if (spinner.getItemAtPosition(i) == translator.getString(selection)
+ ) {
+ spinner.setSelection(i); break
+ }
}
private fun loadData() {
presenter.loadData(DataMode.ADVERTISING_DATA)
presenter.loadData(DataMode.SCAN_RESPONSE_DATA)
- handleAddData(ll_data_advertising_data.findViewById(R.id.data_flags), DataType.FLAGS, DataMode.ADVERTISING_DATA)
+
+ handleAddData(
+ binding.advConfigData.llDataAdvertisingData.dataFlags,
+ DataType.FLAGS,
+ DataMode.ADVERTISING_DATA
+ )
}
private fun prepareDataSpinners() {
- prepareDataSpinner(sp_advertising_data, ll_data_advertising_data, DataMode.ADVERTISING_DATA)
- prepareDataSpinner(sp_scan_response_data, ll_data_scan_resp_data, DataMode.SCAN_RESPONSE_DATA)
- btn_add_advertising_data.setOnClickListener { sp_advertising_data.performClick() }
- btn_add_scan_response_data.setOnClickListener { sp_scan_response_data.performClick() }
+ prepareDataSpinner(
+ binding.advConfigData.spAdvertisingData,
+ binding.advConfigData.llDataAdvertisingData,
+ DataMode.ADVERTISING_DATA
+ )
+ prepareDataSpinner(
+ binding.advConfigData.spScanResponseData,
+ binding.advConfigData.llDataScanRespData,
+ DataMode.SCAN_RESPONSE_DATA
+ )
+ binding.advConfigData.btnAddAdvertisingData.setOnClickListener {
+ binding.advConfigData.spAdvertisingData.performClick()
+ }
+ binding.advConfigData.btnAddScanResponseData.setOnClickListener {
+ binding.advConfigData.spScanResponseData.performClick()
+ }
}
override fun onDataLoaded(data: DataPacket?, mode: DataMode) {
- val dataContainer = if (mode == DataMode.ADVERTISING_DATA) ll_data_advertising_data else ll_data_scan_resp_data
+ val dataContainer =
+ if (mode == DataMode.ADVERTISING_DATA) {
+ binding.advConfigData.llDataAdvertisingData
+ } else {
+ binding.advConfigData.llDataScanRespData
+ }
data?.let {
if (data.includeCompleteLocalName)
- handleAddData(dataContainer.findViewById(R.id.data_complete_local_name), DataType.COMPLETE_LOCAL_NAME, mode)
+ handleAddData(
+ dataContainer.dataCompleteLocalName,
+ DataType.COMPLETE_LOCAL_NAME,
+ mode
+ )
if (data.manufacturers.isNotEmpty())
- for (item in data.manufacturers) handleAddData(dataContainer.findViewById(R.id.data_manufacturer_data), DataType.MANUFACTURER_SPECIFIC_DATA, mode, item)
+ for (item in data.manufacturers) handleAddData(
+ dataContainer.dataManufacturerData,
+ DataType.MANUFACTURER_SPECIFIC_DATA,
+ mode,
+ item
+ )
if (data.includeTxPower)
- handleAddData(dataContainer.findViewById(R.id.data_tx_power), DataType.TX_POWER, mode)
+ handleAddData(
+ dataContainer.dataTxPower,
+ DataType.TX_POWER,
+ mode
+ )
if (data.services16Bit.isNotEmpty())
- handleAddData(dataContainer.findViewById(R.id.data_16bit_services), DataType.COMPLETE_16_BIT, mode, data.services16Bit)
+ handleAddData(
+
+ dataContainer.data16bitServices,
+ DataType.COMPLETE_16_BIT,
+ mode,
+ data.services16Bit
+ )
if (data.services128Bit.isNotEmpty())
- handleAddData(dataContainer.findViewById(R.id.data_128bit_services), DataType.COMPLETE_128_BIT, mode, data.services128Bit)
+ handleAddData(
+ //dataContainer.findViewById(R.id.data_128bit_services),
+ dataContainer.data128bitServices,
+ DataType.COMPLETE_128_BIT,
+ mode,
+ data.services128Bit
+ )
}
}
- private fun prepareDataSpinner(spinner: Spinner, dataContainer: View, mode: DataMode) {
+ private fun prepareDataSpinner(spinner: Spinner, dataContainer: AdvertiserDataContainerBinding, mode: DataMode) {
spinner.setSelection(0)
- spinner.adapter = DataTypeAdapter(this, translator.getAdvertisingDataTypes(), object : DataTypeAdapter.Callback {
- override fun onItemClick(position: Int) {
- when (position) {
- 0 -> handleAddData(dataContainer.findViewById(R.id.data_complete_local_name), DataType.COMPLETE_LOCAL_NAME, mode)
- 1 -> {
- currentFocus?.clearFocus()
- hideKeyboard()
- handleAddData(dataContainer.findViewById(R.id.data_manufacturer_data), DataType.MANUFACTURER_SPECIFIC_DATA, mode)
+ spinner.adapter = DataTypeAdapter(
+ this,
+ translator.getAdvertisingDataTypes(),
+ object : DataTypeAdapter.Callback {
+ override fun onItemClick(position: Int) {
+ when (position) {
+ 0 -> handleAddData(
+ //dataContainer.findViewById(R.id.data_complete_local_name),
+ dataContainer.dataCompleteLocalName,
+ DataType.COMPLETE_LOCAL_NAME,
+ mode
+ )
+
+ 1 -> {
+ currentFocus?.clearFocus()
+ hideKeyboard()
+ handleAddData(
+ //dataContainer.findViewById(R.id.data_manufacturer_data),
+ dataContainer.dataManufacturerData,
+ DataType.MANUFACTURER_SPECIFIC_DATA,
+ mode
+ )
+ }
+
+ 2 -> handleAddData(dataContainer.dataTxPower, DataType.TX_POWER, mode)
+ 3 -> handleAddData(
+ dataContainer.data16bitServices,
+ DataType.COMPLETE_16_BIT,
+ mode
+ )
+
+ 4 -> handleAddData(
+ dataContainer.data128bitServices,
+ DataType.COMPLETE_128_BIT,
+ mode
+ )
}
- 2 -> handleAddData(dataContainer.data_tx_power, DataType.TX_POWER, mode)
- 3 -> handleAddData(dataContainer.data_16bit_services, DataType.COMPLETE_16_BIT, mode)
- 4 -> handleAddData(dataContainer.data_128bit_services, DataType.COMPLETE_128_BIT, mode)
}
- }
- })
+ })
}
- private fun handleAddData(layout: ViewGroup, type: DataType, mode: DataMode, extra: Any? = null) {
+ private fun handleAddData(
+ layout: ViewGroup,
+ type: DataType,
+ mode: DataMode,
+ extra: Any? = null
+ ) {
val baseContainer = prepareBaseContainer(layout, type)
when (type) {
DataType.FLAGS -> addFlagsData(layout, baseContainer)
- DataType.COMPLETE_16_BIT -> addServiceData(layout, baseContainer, mode, DataType.COMPLETE_16_BIT, extra)
- DataType.COMPLETE_128_BIT -> addServiceData(layout, baseContainer, mode, DataType.COMPLETE_128_BIT, extra)
- DataType.COMPLETE_LOCAL_NAME -> addCompleteLocalNameData(layout, baseContainer, mode)
+ DataType.COMPLETE_16_BIT -> addServiceData(
+ layout,
+ baseContainer,
+ mode,
+ DataType.COMPLETE_16_BIT,
+ extra
+ )
+
+ DataType.COMPLETE_128_BIT -> addServiceData(
+ layout,
+ baseContainer,
+ mode,
+ DataType.COMPLETE_128_BIT,
+ extra
+ )
+
+ DataType.COMPLETE_LOCAL_NAME -> addCompleteLocalNameData(
+ layout,
+ baseContainer,
+ mode
+ )
+
DataType.TX_POWER -> addTxPowerData(layout, baseContainer, mode)
- DataType.MANUFACTURER_SPECIFIC_DATA -> addManufacturerSpecificData(layout, baseContainer, mode, extra)
+ DataType.MANUFACTURER_SPECIFIC_DATA -> addManufacturerSpecificData(
+ layout,
+ baseContainer,
+ mode,
+ extra
+ )
}
}
- private fun addFlagsData(layout: ViewGroup, baseContainer: View) {
- baseContainer.ib_remove.visibility = View.INVISIBLE
- val itemContainer = prepareItemContainer(baseContainer, getString(R.string.advertiser_label_flags_default))
- itemContainer.ib_remove.visibility = View.GONE
- baseContainer.ll_data.addView(itemContainer)
- layout.addView(baseContainer)
+ private fun addFlagsData(layout: ViewGroup, baseContainer: DataTypeLayoutBinding) {
+ baseContainer.ibRemove.visibility = View.INVISIBLE
+ val itemContainer =
+ prepareItemContainer(baseContainer, getString(R.string.advertiser_label_flags_default))
+ itemContainer.ibRemove.visibility = View.GONE
+ baseContainer.llData.addView(itemContainer.root)
+ layout.addView(baseContainer.root)
}
- private fun addServiceData(layout: ViewGroup, baseContainer: View, mode: DataMode, type: DataType, extra: Any? = null) {
+ private fun addServiceData(
+ layout: ViewGroup,
+ baseContainer: DataTypeLayoutBinding,
+ mode: DataMode,
+ type: DataType,
+ extra: Any? = null
+ ) {
baseContainer.apply {
- ib_remove.setOnClickListener { layout.removeView(baseContainer) }
- btn_add_service.apply {
+ ibRemove.setOnClickListener { layout.removeView(baseContainer.root) }
+ btnAddService.apply {
visibility = View.VISIBLE
- text = if (type == DataType.COMPLETE_16_BIT) getString(R.string.advertiser_button_add_16bit_service) else getString(R.string.advertiser_button_add_128bit_service)
+ text =
+ if (type == DataType.COMPLETE_16_BIT) getString(R.string.advertiser_button_add_16bit_service) else getString(
+ R.string.advertiser_button_add_128bit_service
+ )
}
- ll_data_spacer.visibility = View.VISIBLE
- (ll_data.layoutParams as ConstraintLayout.LayoutParams).apply {
- endToEnd = ib_remove.id
- topToBottom = ib_remove.id
+ llDataSpacer.visibility = View.VISIBLE
+ (llData.layoutParams as ConstraintLayout.LayoutParams).apply {
+ endToEnd = ibRemove.id
+ topToBottom = ibRemove.id
}
- ll_data.requestLayout()
+ llData.requestLayout()
setDataSpinnerItemState(false, mode, if (type == DataType.COMPLETE_16_BIT) 3 else 4)
- btn_add_service.setOnClickListener {
+ btnAddService.setOnClickListener {
currentFocus?.clearFocus()
hideKeyboard()
if (type == DataType.COMPLETE_16_BIT) {
Service16BitDataDialog(object : Service16BitDataDialog.Callback {
override fun onSave(service: Service16Bit) {
- val serviceItem = prepareItemContainer(baseContainer, service.toString())
+ val serviceItem =
+ prepareItemContainer(baseContainer, service.toString())
presenter.include16BitService(mode, service)
- serviceItem.ib_remove.setOnClickListener {
+ serviceItem.ibRemove.setOnClickListener {
presenter.exclude16BitService(mode, service)
- ll_data.removeView(serviceItem)
+ llData.removeView(serviceItem.root)
}
- ll_data.addView(serviceItem)
+ llData.addView(serviceItem.root)
}
}).show(supportFragmentManager, "dialog_16bit_service_data")
} else {
Service128BitDataDialog(object : Service128BitDataDialog.Callback {
override fun onSave(service: Service128Bit) {
- val serviceItem = prepareItemContainer(baseContainer, service.uuid.toString())
+ val serviceItem =
+ prepareItemContainer(baseContainer, service.uuid.toString())
presenter.include128BitService(mode, service)
- serviceItem.ib_remove.setOnClickListener {
+ serviceItem.ibRemove.setOnClickListener {
presenter.exclude128BitService(mode, service)
- ll_data.removeView(serviceItem)
+ llData.removeView(serviceItem.root)
}
- ll_data.addView(serviceItem)
+ llData.addView(serviceItem.root)
}
}).show(supportFragmentManager, "dialog_128bit_service_data")
}
}
- ib_remove.setOnClickListener {
+ ibRemove.setOnClickListener {
currentFocus?.clearFocus()
hideKeyboard()
- val count = ll_data.childCount
+ val count = llData.childCount
removeServicesIfAllowed(layout, baseContainer, count, mode, type)
}
extra?.let {
for (service in extra as List<*>) {
- val serviceItem = prepareItemContainer(baseContainer, if (service is Service16Bit) service.toString() else (service as Service128Bit).uuid.toString())
+ val serviceItem = prepareItemContainer(
+ baseContainer,
+ if (service is Service16Bit) service.toString() else (service as Service128Bit).uuid.toString()
+ )
- serviceItem.ib_remove.setOnClickListener {
+ serviceItem.ibRemove.setOnClickListener {
if (service is Service16Bit) presenter.exclude16BitService(mode, service)
- else if (service is Service128Bit) presenter.exclude128BitService(mode, service)
- ll_data.removeView(serviceItem)
+ else if (service is Service128Bit) presenter.exclude128BitService(
+ mode,
+ service
+ )
+ llData.removeView(serviceItem.root)
}
- ll_data.addView(serviceItem)
+ llData.addView(serviceItem.root)
}
}
}
- layout.addView(baseContainer)
+ layout.addView(baseContainer.root)
}
@SuppressLint("MissingPermission")
- private fun addCompleteLocalNameData(layout: ViewGroup, baseContainer: View, mode: DataMode) {
- val itemContainer = prepareItemContainer(baseContainer, BluetoothAdapter.getDefaultAdapter().name)
- itemContainer.ib_remove.visibility = View.GONE
+ private fun addCompleteLocalNameData(
+ layout: ViewGroup, baseContainer: DataTypeLayoutBinding,
+ mode: DataMode
+ ) {
+ val itemContainer =
+ prepareItemContainer(baseContainer, BluetoothAdapter.getDefaultAdapter().name)
+ itemContainer.ibRemove.visibility = View.GONE
setDataSpinnerItemState(false, mode, 0)
presenter.includeCompleteLocalName(mode)
- baseContainer.ib_remove.setOnClickListener {
- layout.removeView(baseContainer)
+ baseContainer.ibRemove.setOnClickListener {
+ layout.removeView(baseContainer.root)
presenter.excludeCompleteLocalName(mode)
setDataSpinnerItemState(true, mode, 0)
}
- baseContainer.ll_data.addView(itemContainer)
- layout.addView(baseContainer)
+ baseContainer.llData.addView(itemContainer.root)
+ layout.addView(baseContainer.root)
}
- private fun addTxPowerData(layout: ViewGroup, baseContainer: View, mode: DataMode) {
- val itemContainer = prepareItemContainer(baseContainer, getString(R.string.unit_value_dbm, getTxPower()))
+ private fun addTxPowerData(
+ layout: ViewGroup, baseContainer: DataTypeLayoutBinding,
+ mode: DataMode
+ ) {
+ val itemContainer =
+ prepareItemContainer(baseContainer, getString(R.string.unit_value_dbm, getTxPower()))
- et_tx_power.addTextChangedListener(object : TextWatcher {
+ binding.advConfigParam.etTxPower.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- if (Validator.isTxPowerValid(et_tx_power.text.toString())) {
- itemContainer.tv_data_text.text = getString(R.string.unit_value_dbm, et_tx_power.text.toString().toInt())
+ if (Validator.isTxPowerValid(binding.advConfigParam.etTxPower.text.toString())) {
+ itemContainer.tvDataText.text =
+ getString(
+ R.string.unit_value_dbm,
+ binding.advConfigParam.etTxPower.text.toString().toInt()
+ )
}
}
})
- itemContainer.ib_remove.visibility = View.GONE
+ itemContainer.ibRemove.visibility = View.GONE
setDataSpinnerItemState(false, mode, 2)
presenter.includeTxPower(mode)
- baseContainer.ib_remove.setOnClickListener {
- layout.removeView(baseContainer)
+ baseContainer.ibRemove.setOnClickListener {
+ layout.removeView(baseContainer.root)
presenter.excludeTxPower(mode)
setDataSpinnerItemState(true, mode, 2)
}
- baseContainer.ll_data.addView(itemContainer)
- layout.addView(baseContainer)
+ baseContainer.llData.addView(itemContainer.root)
+ layout.addView(baseContainer.root)
}
- private fun addManufacturerSpecificData(layout: ViewGroup, baseContainer: View, mode: DataMode, extra: Any? = null) {
+ private fun addManufacturerSpecificData(
+ layout: ViewGroup,
+ baseContainer: DataTypeLayoutBinding,
+ mode: DataMode,
+ extra: Any? = null
+ ) {
if (extra == null) {
- ManufacturerDataDialog(presenter.getManufacturers(mode), object : ManufacturerDataDialog.Callback {
- override fun onSave(manufacturer: Manufacturer) {
- val itemContainer = prepareItemContainer(baseContainer, manufacturer.getAsDescriptiveText())
- itemContainer.ib_remove.visibility = View.GONE
-
- presenter.includeManufacturerSpecificData(mode, manufacturer)
+ ManufacturerDataDialog(
+ presenter.getManufacturers(mode),
+ object : ManufacturerDataDialog.Callback {
+ override fun onSave(manufacturer: Manufacturer) {
+ val itemContainer =
+ prepareItemContainer(baseContainer, manufacturer.getAsDescriptiveText())
+ itemContainer.ibRemove.visibility = View.GONE
+
+ presenter.includeManufacturerSpecificData(mode, manufacturer)
+
+ baseContainer.ibRemove.setOnClickListener {
+ presenter.excludeManufacturerSpecificData(mode, manufacturer)
+ layout.removeView(baseContainer.root)
+ }
- baseContainer.ib_remove.setOnClickListener {
- presenter.excludeManufacturerSpecificData(mode, manufacturer)
- layout.removeView(baseContainer)
+ baseContainer.llData.addView(itemContainer.root)
+ layout.addView(baseContainer.root)
}
-
- baseContainer.ll_data.addView(itemContainer)
- layout.addView(baseContainer)
- }
- }).show(supportFragmentManager, "dialog_manufacturer_data")
+ }).show(supportFragmentManager, "dialog_manufacturer_data")
} else {
val manufacturer = extra as Manufacturer
- val itemContainer = prepareItemContainer(baseContainer, manufacturer.getAsDescriptiveText())
- itemContainer.ib_remove.visibility = View.GONE
+ val itemContainer =
+ prepareItemContainer(baseContainer, manufacturer.getAsDescriptiveText())
+ itemContainer.ibRemove.visibility = View.GONE
- baseContainer.ib_remove.setOnClickListener {
+ baseContainer.ibRemove.setOnClickListener {
presenter.excludeManufacturerSpecificData(mode, manufacturer)
- layout.removeView(baseContainer)
+ layout.removeView(baseContainer.root)
}
- baseContainer.ll_data.addView(itemContainer)
- layout.addView(baseContainer)
+ baseContainer.llData.addView(itemContainer.root)
+ layout.addView(baseContainer.root)
}
}
- private fun prepareBaseContainer(layout: ViewGroup, type: DataType): View {
- val container = LayoutInflater.from(this@AdvertiserConfigActivity).inflate(R.layout.data_type_layout, layout, false)
- setBaseContainerTitle(container, type)
- return container
+ private fun prepareBaseContainer(layout: ViewGroup, type: DataType):
+ DataTypeLayoutBinding {
+ lateinit var binding: DataTypeLayoutBinding
+ val container = LayoutInflater.from(this@AdvertiserConfigActivity)
+ binding = DataTypeLayoutBinding.inflate(container)
+ setBaseContainerTitle(binding, type)
+ return binding
}
- private fun setBaseContainerTitle(container: View, type: DataType) {
- val name = "".plus(type.getIdentifier().plus(" ").plus(translator.getDataTypeAsString(type)))
- container.tv_name.text = Html.fromHtml(name, Html.FROM_HTML_MODE_LEGACY)
+ private fun prepareItemContainer(
+ baseContainer: DataTypeLayoutBinding,
+ text: String
+ ): DataTypeItemBinding {
+ lateinit var binding: DataTypeItemBinding
+ val container = LayoutInflater.from(this@AdvertiserConfigActivity)
+ binding = DataTypeItemBinding.inflate(container)
+ binding.tvDataText.text = text
+ return binding
}
- private fun prepareItemContainer(baseContainer: View, text: String): View {
- val container = LayoutInflater.from(this@AdvertiserConfigActivity).inflate(R.layout.data_type_item, baseContainer.ll_data, false)
- container.tv_data_text.text = text
- return container
+ private fun setBaseContainerTitle(container: DataTypeLayoutBinding, type: DataType) {
+ val name = "".plus(
+ type.getIdentifier().plus(" ").plus(translator.getDataTypeAsString(type))
+ )
+ container.tvName.text = Html.fromHtml(name, Html.FROM_HTML_MODE_LEGACY)
}
- private fun removeServicesIfAllowed(layout: ViewGroup, container: View, count: Int, mode: DataMode, type: DataType) {
+ private fun removeServicesIfAllowed(
+ layout: ViewGroup,
+ container: DataTypeLayoutBinding,
+ count: Int,
+ mode: DataMode,
+ type: DataType
+ ) {
if (count > 0 && AdvertiserStorage(this).shouldDisplayRemoveServicesDialog()) {
RemoveServicesDialog(object : RemoveServicesDialog.Callback {
override fun onOkClicked() {
presenter.excludeServices(mode, type)
- layout.removeView(container)
- setDataSpinnerItemState(true, mode, if (type == DataType.COMPLETE_16_BIT) 3 else 4)
+ layout.removeView(container.root)
+ setDataSpinnerItemState(
+ true,
+ mode,
+ if (type == DataType.COMPLETE_16_BIT) 3 else 4
+ )
}
}).show(supportFragmentManager, "dialog_remove_services")
} else {
presenter.excludeServices(mode, type)
- layout.removeView(container)
+ layout.removeView(container.root)
setDataSpinnerItemState(true, mode, if (type == DataType.COMPLETE_16_BIT) 3 else 4)
}
}
private fun setDataSpinnerItemState(enabled: Boolean, mode: DataMode, position: Int) {
- if (mode == DataMode.ADVERTISING_DATA) (sp_advertising_data.adapter as DataTypeAdapter).setItemState(enabled, position)
- else (sp_scan_response_data.adapter as DataTypeAdapter).setItemState(enabled, position)
- }
- override fun updateAvailableBytes(advDataBytes: Int, scanRespDataBytes: Int, maxPacketSize: Int, includeFlags: Boolean) {
- changeDataContainerPadding(advDataBytes < maxPacketSize, ll_data_advertising_data)
- changeDataContainerPadding(scanRespDataBytes < maxPacketSize, ll_data_scan_resp_data)
-
- ll_data_advertising_data.findViewById(R.id.data_flags).visibility = if (includeFlags) View.VISIBLE else View.GONE
+ if (mode == DataMode.ADVERTISING_DATA) (binding.advConfigData.spAdvertisingData.adapter as DataTypeAdapter)
+ .setItemState(
+ enabled,
+ position
+ )
+ else (binding.advConfigData.spScanResponseData.adapter as DataTypeAdapter).setItemState(
+ enabled,
+ position
+ )
+ }
- tv_adv_data_available_bytes.setTextAppearance(if (advDataBytes >= 0) R.style.TextViewNoteInfo else R.style.TextViewNoteWarning)
- tv_adv_data_available_bytes.text = (if (advDataBytes >= 0) getString(R.string.advertiser_note_x_bytes_available, advDataBytes)
+ override fun updateAvailableBytes(
+ advDataBytes: Int,
+ scanRespDataBytes: Int,
+ maxPacketSize: Int,
+ includeFlags: Boolean
+ ) {
+ changeDataContainerPadding(
+ advDataBytes < maxPacketSize,
+ binding.advConfigData.llDataAdvertisingData.root
+ )
+ changeDataContainerPadding(
+ scanRespDataBytes < maxPacketSize,
+ binding.advConfigData.llDataScanRespData.root
+ )
+
+ binding.advConfigData.llDataAdvertisingData.dataFlags.visibility =
+ if (includeFlags) View.VISIBLE else View.GONE
+
+ binding.advConfigData.tvAdvDataAvailableBytes.setTextAppearance(if (advDataBytes >= 0) R.style.TextViewNoteInfo else R.style.TextViewNoteWarning)
+ binding.advConfigData.tvAdvDataAvailableBytes.text = (if (advDataBytes >= 0) getString(
+ R.string.advertiser_note_x_bytes_available,
+ advDataBytes
+ )
else getString(R.string.advertiser_note_x_bytes_beyond, -advDataBytes))
- tv_scan_resp_available_bytes.setTextAppearance(if (scanRespDataBytes >= 0) R.style.TextViewNoteInfo else R.style.TextViewNoteWarning)
- tv_scan_resp_available_bytes.text = (if (scanRespDataBytes >= 0) getString(R.string.advertiser_note_x_bytes_available, scanRespDataBytes)
- else getString(R.string.advertiser_note_x_bytes_beyond, -scanRespDataBytes))
+ binding.advConfigData.tvScanRespAvailableBytes.setTextAppearance(if (scanRespDataBytes >= 0) R.style.TextViewNoteInfo else R.style.TextViewNoteWarning)
+ binding.advConfigData.tvScanRespAvailableBytes.text =
+ (if (scanRespDataBytes >= 0) getString(
+ R.string.advertiser_note_x_bytes_available,
+ scanRespDataBytes
+ )
+ else getString(R.string.advertiser_note_x_bytes_beyond, -scanRespDataBytes))
}
private fun changeDataContainerPadding(showPadding: Boolean, container: View) {
- val padding8Dp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f, resources.displayMetrics).toInt()
+ val padding8Dp =
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f, resources.displayMetrics)
+ .toInt()
if (showPadding) container.setPadding(0, padding8Dp, 0, padding8Dp)
else container.setPadding(0, 0, 0, 0)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/adapters/AdvertiserAdapter.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/adapters/AdvertiserAdapter.kt
index ddbb72d0..875f3fde 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/adapters/AdvertiserAdapter.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/adapters/AdvertiserAdapter.kt
@@ -112,9 +112,13 @@ class AdvertiserAdapter(
}
private fun handleDetailsView(item: Advertiser) {
+ println("Show Advertiser Data ${item.data}")
+
viewBinding.llAdvertisementDetails.apply {
removeAllViews()
- addView(AdvertiserDetails(itemView.context).getAdvertiserDetailsView(item, translator))
+
+ val advertiserDetailContainer = AdvertiserDetails(itemView.context).getAdvertiserDetailsView(item, translator)
+ addView(advertiserDetailContainer.rootView,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
}
toggleDetailsView(item.displayDetailsView)
}
@@ -131,6 +135,7 @@ class AdvertiserAdapter(
}
fun toggleDetailsView(displayDetails: Boolean) {
+ println("displayDetails:--> $displayDetails")
viewBinding.llAdvertisementDetails.visibility = if (displayDetails) View.VISIBLE else View.GONE
viewBinding.expandArrow.setState(displayDetails)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/adapters/DataTypeAdapter.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/adapters/DataTypeAdapter.kt
index e049539a..c60f5d12 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/adapters/DataTypeAdapter.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/adapters/DataTypeAdapter.kt
@@ -6,13 +6,18 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.LinearLayout
-import com.siliconlabs.bledemo.features.configure.advertiser.models.DataTypeItem
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.spinner_data_type_item_layout.view.*
+import com.siliconlabs.bledemo.databinding.SpinnerDataTypeItemLayoutBinding
+import com.siliconlabs.bledemo.features.configure.advertiser.models.DataTypeItem
-class DataTypeAdapter(context: Context,
- private val values: List,
- private val callback: Callback) : ArrayAdapter(context, R.layout.spinner_data_type_item_layout, values) {
+//import kotlinx.android.synthetic.main.spinner_data_type_item_layout.view.*
+
+class DataTypeAdapter(
+ context: Context,
+ private val values: List,
+ private val callback: Callback
+) : ArrayAdapter(context, R.layout.spinner_data_type_item_layout, values) {
+ private lateinit var binding: SpinnerDataTypeItemLayoutBinding
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
return createViewFromResource(position, parent)
@@ -22,15 +27,25 @@ class DataTypeAdapter(context: Context,
return createViewFromResource(position, parent)
}
+
private fun createViewFromResource(position: Int, parent: ViewGroup?): View {
- return (LayoutInflater.from(context).inflate(R.layout.spinner_data_type_item_layout, parent, false) as LinearLayout).apply {
- tv_identifier.text = values[position].identifier
- tv_name.text = values[position].name
- tv_identifier.isEnabled = isEnabled(position)
- tv_name.isEnabled = isEnabled(position)
+ binding = SpinnerDataTypeItemLayoutBinding.inflate(LayoutInflater.from(context)).apply {
+ tvIdentifier.text = values[position].identifier
+ tvName.text = values[position].name
+ tvIdentifier.isEnabled = isEnabled(position)
+ tvName.isEnabled = isEnabled(position)
+
+ tvName.setOnClickListener {
+ callback.onItemClick(position)
+ }
+ tvIdentifier.setOnClickListener {
+ callback.onItemClick(position)
+ }
+ //TODO
+ //if (isEnabled(position)) setOnClickListener { callback.onItemClick(position) }
- if (isEnabled(position)) setOnClickListener { callback.onItemClick(position) }
}
+ return binding.root
}
override fun isEnabled(position: Int): Boolean {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/LeaveAdvertiserConfigDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/LeaveAdvertiserConfigDialog.kt
index 6ee5b7df..315ec04b 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/LeaveAdvertiserConfigDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/LeaveAdvertiserConfigDialog.kt
@@ -7,30 +7,35 @@ import android.view.ViewGroup
import com.siliconlabs.bledemo.features.configure.advertiser.utils.AdvertiserStorage
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_info_ok_cancel.*
+import com.siliconlabs.bledemo.databinding.DialogInfoOkCancelBinding
+
+//mport kotlinx.android.synthetic.main.dialog_info_ok_cancel.*
class LeaveAdvertiserConfigDialog(var callback: Callback) : BaseDialogFragment() {
+ private lateinit var binding:DialogInfoOkCancelBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_info_ok_cancel, container, false)
+ // return inflater.inflate(R.layout.dialog_info_ok_cancel, container, false)
+ binding = DialogInfoOkCancelBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- tv_dialog_title.text = context?.getString(R.string.title_unsaved_changes)
- tv_dialog_content.text = context?.getString(R.string.advertiser_note_leave_advertiser_config)
+ binding.tvDialogTitle.text = context?.getString(R.string.title_unsaved_changes)
+ binding.tvDialogContent.text = context?.getString(R.string.advertiser_note_leave_advertiser_config)
- btn_ok.text = context?.getString(R.string.button_yes)
- btn_cancel.text = context?.getString(R.string.button_no)
+ binding.btnOk.text = context?.getString(R.string.button_yes)
+ binding.btnCancel.text = context?.getString(R.string.button_no)
- btn_ok.setOnClickListener {
- if (cb_dont_show_again.isChecked) AdvertiserStorage(requireContext()).setShouldDisplayLeaveAdvertiserConfigDialog(false)
+ binding.btnOk.setOnClickListener {
+ if (binding.cbDontShowAgain.isChecked) AdvertiserStorage(requireContext()).setShouldDisplayLeaveAdvertiserConfigDialog(false)
callback.onYesClicked()
dismiss()
}
- btn_cancel.setOnClickListener {
+ binding.btnCancel.setOnClickListener {
dismiss()
callback.onNoClicked()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/ManufacturerDataDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/ManufacturerDataDialog.kt
index 91338a94..d38b64b4 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/ManufacturerDataDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/ManufacturerDataDialog.kt
@@ -15,32 +15,48 @@ import com.siliconlabs.bledemo.features.configure.advertiser.models.Manufacturer
import com.siliconlabs.bledemo.features.configure.advertiser.utils.Validator
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.DialogDataManufacturerBinding
import com.siliconlabs.bledemo.utils.Converters
-import kotlinx.android.synthetic.main.dialog_data_manufacturer.view.*
-class ManufacturerDataDialog(private val manufacturers: List, val callback: Callback) : BaseDialogFragment() {
+//import kotlinx.android.synthetic.main.dialog_data_manufacturer.view.*
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_data_manufacturer, container, false).apply {
+class ManufacturerDataDialog(
+ private val manufacturers: List,
+ val callback: Callback
+) : BaseDialogFragment() {
- btn_clear.setOnClickListener {
- et_company_identifier.setText("")
- et_data_in_hex_format.setText("")
+ private lateinit var binding: DialogDataManufacturerBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogDataManufacturerBinding.inflate(inflater, container, false).apply {
+
+ btnClear.setOnClickListener {
+ etCompanyIdentifier.setText("")
+ etDataInHexFormat.setText("")
}
- btn_cancel.setOnClickListener {
+ btnCancel.setOnClickListener {
dismiss()
}
- btn_save.setOnClickListener {
- handleSave(et_company_identifier, et_data_in_hex_format)
+ btnSave.setOnClickListener {
+ handleSave(etCompanyIdentifier, etDataInHexFormat)
dismiss()
}
- verifyDataCorrectness(et_company_identifier, et_data_in_hex_format, btn_save, tv_id_already_exists)
- handleClickOnCompanyIdentifiers(btn_company_identifiers)
-
+ verifyDataCorrectness(
+ etCompanyIdentifier,
+ etDataInHexFormat,
+ btnSave,
+ tvIdAlreadyExists
+ )
+ handleClickOnCompanyIdentifiers(btnCompanyIdentifiers)
}
+ return binding.root
}
private fun identifierCurrentlyExists(currentId: String): Boolean {
@@ -53,15 +69,23 @@ class ManufacturerDataDialog(private val manufacturers: List, val
}
}
- private fun verifyDataCorrectness(etIdentifier: EditText, etData: EditText, btnSave: Button, tvNote: TextView) {
+ private fun verifyDataCorrectness(
+ etIdentifier: EditText,
+ etData: EditText,
+ btnSave: Button,
+ tvNote: TextView
+ ) {
etIdentifier.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val id = etIdentifier.text.toString()
val data = etData.text.toString()
- tvNote.visibility = if(identifierCurrentlyExists(id)) View.VISIBLE else View.GONE
- btnSave.isEnabled = (Validator.isCompanyIdentifierValid(id) && Validator.isCompanyDataValid(data) && !identifierCurrentlyExists(id))
+ tvNote.visibility = if (identifierCurrentlyExists(id)) View.VISIBLE else View.GONE
+ btnSave.isEnabled =
+ (Validator.isCompanyIdentifierValid(id) && Validator.isCompanyDataValid(data) && !identifierCurrentlyExists(
+ id
+ ))
}
})
@@ -71,15 +95,19 @@ class ManufacturerDataDialog(private val manufacturers: List, val
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val id = etIdentifier.text.toString()
val data = etData.text.toString()
- tvNote.visibility = if(identifierCurrentlyExists(id)) View.VISIBLE else View.GONE
- btnSave.isEnabled = (Validator.isCompanyIdentifierValid(id) && Validator.isCompanyDataValid(data) && !identifierCurrentlyExists(id))
+ tvNote.visibility = if (identifierCurrentlyExists(id)) View.VISIBLE else View.GONE
+ btnSave.isEnabled =
+ (Validator.isCompanyIdentifierValid(id) && Validator.isCompanyDataValid(data) && !identifierCurrentlyExists(
+ id
+ ))
}
})
}
private fun handleClickOnCompanyIdentifiers(btn: Button) {
btn.setOnClickListener {
- val uriUrl = Uri.parse("https://" + getString(R.string.advertiser_url_company_identifiers))
+ val uriUrl =
+ Uri.parse("https://" + getString(R.string.advertiser_url_company_identifiers))
val launchBrowser = Intent(Intent.ACTION_VIEW, uriUrl)
startActivity(launchBrowser)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/RemoveAdvertiserDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/RemoveAdvertiserDialog.kt
index 00257b96..7c9c360a 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/RemoveAdvertiserDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/RemoveAdvertiserDialog.kt
@@ -7,23 +7,34 @@ import android.view.ViewGroup
import com.siliconlabs.bledemo.features.configure.advertiser.utils.AdvertiserStorage
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_info_ok_cancel.view.*
+import com.siliconlabs.bledemo.databinding.DialogInfoOkCancelBinding
-class RemoveAdvertiserDialog(val callback: Callback) : BaseDialogFragment() {
+//import kotlinx.android.synthetic.main.dialog_info_ok_cancel.view.*
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_info_ok_cancel, container, false).apply {
+class RemoveAdvertiserDialog(val callback: Callback) : BaseDialogFragment() {
+ private lateinit var binding: DialogInfoOkCancelBinding
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogInfoOkCancelBinding.inflate(inflater, container, false).apply {
- tv_dialog_title.text = context.getString(R.string.advertiser_title_remove_advertiser)
- tv_dialog_content.text = context.getString(R.string.advertiser_note_remove_advertiser)
+ tvDialogTitle.text =
+ requireContext().getString(R.string.advertiser_title_remove_advertiser)
+ tvDialogContent.text =
+ requireContext().getString(R.string.advertiser_note_remove_advertiser)
- btn_ok.setOnClickListener {
- if (cb_dont_show_again.isChecked) AdvertiserStorage(context).setShouldDisplayRemoveAdvertiserDialog(false)
+ btnOk.setOnClickListener {
+ if (binding.cbDontShowAgain.isChecked) AdvertiserStorage(requireContext()).setShouldDisplayRemoveAdvertiserDialog(
+ false
+ )
callback.onOkClicked()
dismiss()
}
- btn_cancel.setOnClickListener { dismiss() }
+ btnCancel.setOnClickListener { dismiss() }
}
+ return binding.root
}
interface Callback {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/RemoveServicesDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/RemoveServicesDialog.kt
index fdca76c1..f7e44485 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/RemoveServicesDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/RemoveServicesDialog.kt
@@ -7,23 +7,35 @@ import android.view.ViewGroup
import com.siliconlabs.bledemo.features.configure.advertiser.utils.AdvertiserStorage
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_info_ok_cancel.view.*
+import com.siliconlabs.bledemo.databinding.DialogInfoOkCancelBinding
+
+//import kotlinx.android.synthetic.main.dialog_info_ok_cancel.view.*
class RemoveServicesDialog(val callback: Callback) : BaseDialogFragment() {
+ private lateinit var binding: DialogInfoOkCancelBinding
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_info_ok_cancel, container, false).apply {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogInfoOkCancelBinding.inflate(inflater, container, false).apply {
- tv_dialog_title.text = context.getString(R.string.advertiser_title_remove_service_list)
- tv_dialog_content.text = context.getString(R.string.advertiser_note_remove_services)
+ tvDialogTitle.text =
+ requireContext().getString(R.string.advertiser_title_remove_service_list)
+ tvDialogContent.text =
+ requireContext().getString(R.string.advertiser_note_remove_services)
- btn_ok.setOnClickListener {
- if (cb_dont_show_again.isChecked) AdvertiserStorage(context).setShouldDisplayRemoveServicesDialog(false)
+ btnOk.setOnClickListener {
+ if (cbDontShowAgain.isChecked) AdvertiserStorage(requireContext()).setShouldDisplayRemoveServicesDialog(
+ false
+ )
callback.onOkClicked()
dismiss()
}
- btn_cancel.setOnClickListener { dismiss() }
+ btnCancel.setOnClickListener { dismiss() }
}
+ return binding.root
}
interface Callback {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/Service128BitDataDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/Service128BitDataDialog.kt
index 1f4b1fc1..dfa62f55 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/Service128BitDataDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/Service128BitDataDialog.kt
@@ -12,22 +12,29 @@ import com.siliconlabs.bledemo.features.configure.advertiser.models.Service128Bi
import com.siliconlabs.bledemo.features.configure.advertiser.utils.Validator
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_data_128bit_service.view.*
+import com.siliconlabs.bledemo.databinding.DialogData128bitServiceBinding
+//import kotlinx.android.synthetic.main.dialog_data_128bit_service.view.*
import java.util.*
class Service128BitDataDialog(val callback: Callback) : BaseDialogFragment() {
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_data_128bit_service, container, false).apply {
- btn_cancel.setOnClickListener { dismiss() }
- btn_save.setOnClickListener {
- handleSave(et_128bit_service)
+ private lateinit var binding: DialogData128bitServiceBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogData128bitServiceBinding.inflate(inflater, container, false).apply {
+ btnCancel.setOnClickListener { dismiss() }
+ btnSave.setOnClickListener {
+ handleSave(et128bitService)
dismiss()
}
- btn_clear.setOnClickListener { et_128bit_service.setText("") }
+ btnClear.setOnClickListener { et128bitService.setText("") }
- handleUuidChanges(et_128bit_service, btn_save)
+ handleUuidChanges(et128bitService, btnSave)
}
+ return binding.root
}
private fun handleSave(et: EditText) {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/Service16BitDataDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/Service16BitDataDialog.kt
index 4e95f82d..ecbd2644 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/Service16BitDataDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/dialogs/Service16BitDataDialog.kt
@@ -20,27 +20,37 @@ import com.siliconlabs.bledemo.features.configure.advertiser.utils.Translator
import com.siliconlabs.bledemo.features.configure.advertiser.utils.Validator
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
-import kotlinx.android.synthetic.main.dialog_data_16bit_service.view.*
-import kotlinx.android.synthetic.main.dialog_data_manufacturer.view.btn_cancel
-import kotlinx.android.synthetic.main.dialog_data_manufacturer.view.btn_save
+import com.siliconlabs.bledemo.databinding.DialogData16bitServiceBinding
+//import kotlinx.android.synthetic.main.dialog_data_16bit_service.view.*
+//import kotlinx.android.synthetic.main.dialog_data_manufacturer.view.btn_cancel
+//import kotlinx.android.synthetic.main.dialog_data_manufacturer.view.btn_save
class Service16BitDataDialog(val callback: Callback) : BaseDialogFragment() {
private lateinit var predefinedServices: List
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_data_16bit_service, container, false).apply {
-
- predefinedServices = Translator(context).get16BitServices()
- val adapter = Service16BitAdapter(context, Translator(context).get16BitServices())
- actv_16bit_services.setAdapter(adapter)
-
- btn_cancel.setOnClickListener { dismiss() }
- btn_save.setOnClickListener { handleSave(actv_16bit_services) }
- btn_clear.setOnClickListener { actv_16bit_services.setText("") }
-
- verifyDataCorrectness(actv_16bit_services, btn_save)
- handleClickOnBluetoothGattServices(btn_bluetooth_gatt_services)
+ private lateinit var binding: DialogData16bitServiceBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogData16bitServiceBinding.inflate(inflater, container, false).apply {
+
+ predefinedServices = Translator(requireContext()).get16BitServices()
+ val adapter = Service16BitAdapter(
+ requireContext(),
+ Translator(requireContext()).get16BitServices()
+ )
+ actv16bitServices.setAdapter(adapter)
+
+ btnCancel.setOnClickListener { dismiss() }
+ btnSave.setOnClickListener { handleSave(actv16bitServices) }
+ btnClear.setOnClickListener { actv16bitServices.setText("") }
+
+ verifyDataCorrectness(actv16bitServices, btnSave)
+ handleClickOnBluetoothGattServices(btnBluetoothGattServices)
}
+ return binding.root
}
private fun handleSave(actv: AutoCompleteTextView) {
@@ -64,14 +74,18 @@ class Service16BitDataDialog(val callback: Callback) : BaseDialogFragment() {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val text = actv.text.toString()
- saveBtn.isEnabled = Validator.isCompanyIdentifierValid(text) || isPredefinedService(text, predefinedServices)
+ saveBtn.isEnabled = Validator.isCompanyIdentifierValid(text) || isPredefinedService(
+ text,
+ predefinedServices
+ )
}
})
}
private fun handleClickOnBluetoothGattServices(button: Button) {
button.setOnClickListener {
- val uriUrl = Uri.parse("https://" + getString(R.string.advertiser_url_bluetooth_gatt_services))
+ val uriUrl =
+ Uri.parse("https://" + getString(R.string.advertiser_url_bluetooth_gatt_services))
val launchBrowser = Intent(Intent.ACTION_VIEW, uriUrl)
startActivity(launchBrowser)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/fragments/AdvertiserFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/fragments/AdvertiserFragment.kt
index 1c79d45c..83a510a4 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/fragments/AdvertiserFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/fragments/AdvertiserFragment.kt
@@ -25,6 +25,7 @@ import com.siliconlabs.bledemo.home_screen.activities.MainActivity
import com.siliconlabs.bledemo.common.other.CardViewListDecoration
import com.siliconlabs.bledemo.home_screen.base.BaseServiceDependentMainMenuFragment
import com.siliconlabs.bledemo.home_screen.base.BluetoothDependent
+import com.siliconlabs.bledemo.home_screen.base.NotificationDependent
class AdvertiserFragment : BaseServiceDependentMainMenuFragment(), AdvertiserAdapter.OnItemClickListener {
@@ -50,8 +51,9 @@ class AdvertiserFragment : BaseServiceDependentMainMenuFragment(), AdvertiserAda
viewModelStore,
AdvertiserViewModel.Factory(AdvertiserStorage(requireContext()))
).get(AdvertiserViewModel::class.java)
- service = (activity as MainActivity).bluetoothService!!
-
+ if(null != (activity as MainActivity).bluetoothService){
+ service = (activity as MainActivity).bluetoothService!!
+ }
initMainViewValues()
setUiListeners()
observeChanges()
@@ -114,6 +116,8 @@ class AdvertiserFragment : BaseServiceDependentMainMenuFragment(), AdvertiserAda
}
}
+
+
private fun initAdapter() {
advertiserAdapter = AdvertiserAdapter(viewModel?.advertisers?.value ?: arrayListOf(), this)
viewBinding.fragmentMainView.rvMainView.apply {
@@ -185,6 +189,7 @@ class AdvertiserFragment : BaseServiceDependentMainMenuFragment(), AdvertiserAda
} else {
fullScreenInfo.root.visibility = View.VISIBLE
rvMainView.visibility = View.GONE
+ restoreHiddenUI()
}
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/viewmodels/AdvertiserViewModel.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/viewmodels/AdvertiserViewModel.kt
index 6f3e9984..e8580cf2 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/viewmodels/AdvertiserViewModel.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/viewmodels/AdvertiserViewModel.kt
@@ -116,7 +116,9 @@ class AdvertiserViewModel(private val advertiserStorage: AdvertiserStorage) : Vi
fun switchAllItemsOff() {
_advertisers.value?.forEachIndexed { index, advertiser ->
- if (advertiser.isRunning) { stopAdvertiserItem(index) }
+ //if (advertiser.isRunning) {
+ stopAdvertiserItem(index)
+ //}
}
saveAdvertiserList()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/views/AdvertiserDetails.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/views/AdvertiserDetails.kt
index c0d3904b..7a5e03ec 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/views/AdvertiserDetails.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/views/AdvertiserDetails.kt
@@ -23,45 +23,46 @@ class AdvertiserDetails(val context: Context) {
val advertisingType = (if (data.isLegacy) context.getString(R.string.advertiser_label_legacy)
else context.getString(R.string.advertiser_label_extended)).plus(" (").plus(translator.getString(data.mode)).plus(")")
- addView(DetailsRow(context, context.getString(R.string.advertiser_title_advertising_type), advertisingType))
- if (!data.isLegacy) addView(DetailsRow(context, context.getString(R.string.Bluetooth_5_Advertising_Extension), getAdvertisingExtensionText(context, translator, item.data)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_title_advertising_type), advertisingType).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
+
+ if (!data.isLegacy) addView(DetailsRow(context, context.getString(R.string.Bluetooth_5_Advertising_Extension), getAdvertisingExtensionText(context, translator, item.data)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
if (data.isAdvertisingData()) {
- if (data.mode.isConnectable()) addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_flags), context.getString(R.string.advertiser_label_flags_default)))
+ if (data.mode.isConnectable()) addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_flags), context.getString(R.string.advertiser_label_flags_default)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
if (data.advertisingData.includeCompleteLocalName)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_local_name), getCompleteLocalName(context, data.advertisingData)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_local_name), getCompleteLocalName(context, data.advertisingData)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
for (manufacturer in data.advertisingData.manufacturers)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_manufacturer_specific_data), getManufacturerData(manufacturer)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_manufacturer_specific_data), getManufacturerData(manufacturer)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
if (data.advertisingData.includeTxPower)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_tx_power), getTxPower(context, data)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_tx_power), getTxPower(context, data)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
if (data.advertisingData.services16Bit.size > 0)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_16bit_service), get16BitServicesText(item.data.advertisingData)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_16bit_service), get16BitServicesText(item.data.advertisingData)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
if (data.advertisingData.services128Bit.size > 0)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_128bit_service), get128BitServicesText(item.data.advertisingData)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_128bit_service), get128BitServicesText(item.data.advertisingData)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
}
if (data.isScanRespData()) {
if (data.scanResponseData.includeCompleteLocalName)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_local_name), getCompleteLocalName(context, data.scanResponseData)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_local_name), getCompleteLocalName(context, data.scanResponseData)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
for (manufacturer in data.scanResponseData.manufacturers)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_manufacturer_specific_data), getManufacturerData(manufacturer)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_manufacturer_specific_data), getManufacturerData(manufacturer)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
if (data.scanResponseData.includeTxPower)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_tx_power), getTxPower(context, data)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_tx_power), getTxPower(context, data)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
if (data.scanResponseData.services16Bit.size > 0)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_16bit_service), get16BitServicesText(item.data.scanResponseData)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_16bit_service), get16BitServicesText(item.data.scanResponseData)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
if (data.scanResponseData.services128Bit.size > 0)
- addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_128bit_service), get128BitServicesText(item.data.scanResponseData)))
+ addView(DetailsRow(context, context.getString(R.string.advertiser_data_type_complete_128bit_service), get128BitServicesText(item.data.scanResponseData)).binding.root,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
}
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/activities/GattServerActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/activities/GattServerActivity.kt
index e6c07df1..8f3a2441 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/activities/GattServerActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/activities/GattServerActivity.kt
@@ -25,17 +25,21 @@ import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.remove
import com.siliconlabs.bledemo.features.configure.gatt_configurator.viewmodels.GattServerViewModel
import com.siliconlabs.bledemo.features.configure.gatt_configurator.viewmodels.GattServerViewModel.Validation
import com.siliconlabs.bledemo.common.other.EqualVerticalItemDecoration
-import kotlinx.android.synthetic.main.activity_gatt_server.*
+import com.siliconlabs.bledemo.databinding.ActivityGattServerBinding
+
+//import kotlinx.android.synthetic.main.activity_gatt_server.*
class GattServerActivity : BaseActivity(), ServiceListener, AddServiceListener {
private lateinit var viewModel: GattServerViewModel
private lateinit var adapter: EditGattServerAdapter
private var savedServerState: GattServer? = null
+ private lateinit var binding: ActivityGattServerBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_gatt_server)
+ binding = ActivityGattServerBinding.inflate(layoutInflater)
+ setContentView(binding.root)
viewModel = ViewModelProvider(this).get(GattServerViewModel::class.java)
initViewModel()
@@ -63,7 +67,12 @@ class GattServerActivity : BaseActivity(), ServiceListener, AddServiceListener {
viewModel.validation.observe(this, Observer {
when (it) {
- Validation.INVALID_NAME -> Toast.makeText(this, R.string.gatt_configurator_toast_invalid_gatt_server_name, Toast.LENGTH_SHORT).show()
+ Validation.INVALID_NAME -> Toast.makeText(
+ this,
+ R.string.gatt_configurator_toast_invalid_gatt_server_name,
+ Toast.LENGTH_SHORT
+ ).show()
+
else -> saveGattServer()
}
})
@@ -79,7 +88,7 @@ class GattServerActivity : BaseActivity(), ServiceListener, AddServiceListener {
}
private fun handleGattServerNameChanges() {
- et_gatt_server_name.addTextChangedListener(object : TextWatcher {
+ binding.etGattServerName.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
@@ -91,7 +100,7 @@ class GattServerActivity : BaseActivity(), ServiceListener, AddServiceListener {
private fun prepopulateFields() {
viewModel.getGattServerName()?.let { name ->
- et_gatt_server_name.setText(name)
+ binding.etGattServerName.setText(name)
}
}
@@ -105,20 +114,21 @@ class GattServerActivity : BaseActivity(), ServiceListener, AddServiceListener {
private fun exitServerConfigView() {
if (hasConfigurationChanged() &&
- GattConfiguratorStorage(this).shouldDisplayLeaveGattServerConfigDialog()) {
+ GattConfiguratorStorage(this).shouldDisplayLeaveGattServerConfigDialog()
+ ) {
LeaveGattServerConfigDialog(object : LeaveGattServerConfigDialog.Callback {
override fun onYesClicked() {
- viewModel.validateGattServer(et_gatt_server_name.text.toString())
+ viewModel.validateGattServer(binding.etGattServerName.text.toString())
}
+
override fun onNoClicked() {
super@GattServerActivity.onBackPressed()
}
}).show(supportFragmentManager, "dialog_leave_gatt_server_config")
- }
- else super@GattServerActivity.onBackPressed()
+ } else super@GattServerActivity.onBackPressed()
}
- private fun hasConfigurationChanged() : Boolean {
+ private fun hasConfigurationChanged(): Boolean {
return savedServerState != viewModel.getGattServer()
}
@@ -130,19 +140,21 @@ class GattServerActivity : BaseActivity(), ServiceListener, AddServiceListener {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.save_gatt_server -> {
- viewModel.validateGattServer(et_gatt_server_name.text.toString())
+ viewModel.validateGattServer(binding.etGattServerName.text.toString())
true
}
+
android.R.id.home -> {
exitServerConfigView()
true
}
+
else -> super.onOptionsItemSelected(item)
}
}
private fun saveGattServer() {
- viewModel.setGattServerName(et_gatt_server_name.text.toString())
+ viewModel.setGattServerName(binding.etGattServerName.text.toString())
val intent = Intent().apply {
putExtra(EXTRA_GATT_SERVER_POSITION, viewModel.getPosition()!!)
putExtra(EXTRA_GATT_SERVER, viewModel.getGattServer())
@@ -154,10 +166,12 @@ class GattServerActivity : BaseActivity(), ServiceListener, AddServiceListener {
private fun initAdapter() {
adapter = EditGattServerAdapter(viewModel.getServiceList()!!, this, this)
- rv_edit_gatt_server.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
- rv_edit_gatt_server.addItemDecoration(
- EqualVerticalItemDecoration(resources.getDimensionPixelSize(R.dimen.edit_gatt_server_adapter_margin)))
- rv_edit_gatt_server.adapter = adapter
+ binding.rvEditGattServer.layoutManager =
+ LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
+ binding.rvEditGattServer.addItemDecoration(
+ EqualVerticalItemDecoration(resources.getDimensionPixelSize(R.dimen.edit_gatt_server_adapter_margin))
+ )
+ binding.rvEditGattServer.adapter = adapter
}
override fun onCopyService(service: Service) {
@@ -179,6 +193,7 @@ class GattServerActivity : BaseActivity(), ServiceListener, AddServiceListener {
}
override fun onBackPressed() {
+ super.onBackPressed()
exitServerConfigView()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/CharacteristicDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/CharacteristicDialog.kt
index 8658cf2c..88b86003 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/CharacteristicDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/CharacteristicDialog.kt
@@ -12,25 +12,35 @@ import android.widget.AutoCompleteTextView
import android.widget.CheckBox
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
+import com.siliconlabs.bledemo.databinding.DialogGattServerCharacteristicBinding
import com.siliconlabs.bledemo.features.configure.gatt_configurator.adapters.Characteristic16BitAdapter
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.*
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.GattUtils
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.Validator
-import kotlinx.android.synthetic.main.dialog_gatt_server_characteristic.*
-import kotlinx.android.synthetic.main.gatt_configurator_initial_value.*
-import kotlinx.android.synthetic.main.dialog_add_characteristic_properties_content.*
-class CharacteristicDialog(val listener: CharacteristicChangeListener, val characteristic: Characteristic = Characteristic()) : BaseDialogFragment() {
+//import kotlinx.android.synthetic.main.dialog_gatt_server_characteristic.*
+//import kotlinx.android.synthetic.main.gatt_configurator_initial_value.*
+//import kotlinx.android.synthetic.main.dialog_add_characteristic_properties_content.*
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_gatt_server_characteristic, container, false)
+class CharacteristicDialog(
+ val listener: CharacteristicChangeListener,
+ val characteristic: Characteristic = Characteristic()
+) : BaseDialogFragment() {
+ private lateinit var binding: DialogGattServerCharacteristicBinding
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogGattServerCharacteristicBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- initACTV(actv_characteristic_name, SearchMode.BY_NAME)
- initACTV(actv_characteristic_uuid, SearchMode.BY_UUID)
+ initACTV(binding.actvCharacteristicName, SearchMode.BY_NAME)
+ initACTV(binding.actvCharacteristicUuid, SearchMode.BY_UUID)
initInitialValueSpinner()
handleClickEvents()
@@ -42,60 +52,68 @@ class CharacteristicDialog(val listener: CharacteristicChangeListener, val chara
}
private fun handleClickEvents() {
- btn_save.setOnClickListener {
+ binding.btnSave.setOnClickListener {
setCharacteristicState()
listener.onCharacteristicChanged(characteristic)
dismiss()
}
- btn_cancel.setOnClickListener {
+ binding.btnCancel.setOnClickListener {
dismiss()
}
- btn_clear.setOnClickListener {
+ binding.btnClear.setOnClickListener {
clearAllFields()
}
}
private fun prepopulateFields() {
- actv_characteristic_name.setText(characteristic.name)
- actv_characteristic_uuid.setText(characteristic.uuid?.uuid)
+ binding.actvCharacteristicName.setText(characteristic.name)
+ binding.actvCharacteristicUuid.setText(characteristic.uuid?.uuid)
prepopulateProperties()
prepopulatePropertyTypes()
prepopulateInitialValue()
}
private fun prepopulateProperties() {
+ // binding.propertiesContent.apply {
characteristic.properties.apply {
- sw_read.isChecked = containsKey(Property.READ)
- sw_write.isChecked = containsKey(Property.WRITE)
- sw_write_without_resp.isChecked = containsKey(Property.WRITE_WITHOUT_RESPONSE)
- sw_reliable_write.isChecked = containsKey(Property.RELIABLE_WRITE)
- sw_notify.isChecked = containsKey(Property.NOTIFY)
- sw_indicate.isChecked = containsKey(Property.INDICATE)
+ binding.propertiesContent.swRead.isChecked = containsKey(Property.READ)
+ binding.propertiesContent.swWrite.isChecked = containsKey(Property.WRITE)
+ binding.propertiesContent.swWriteWithoutResp.isChecked =
+ containsKey(Property.WRITE_WITHOUT_RESPONSE)
+ binding.propertiesContent.swReliableWrite.isChecked =
+ containsKey(Property.RELIABLE_WRITE)
+ binding.propertiesContent.swNotify.isChecked = containsKey(Property.NOTIFY)
+ binding.propertiesContent.swIndicate.isChecked = containsKey(Property.INDICATE)
}
+
}
private fun prepopulatePropertyTypes() {
characteristic.properties.apply {
this[Property.READ]?.apply {
- cb_read_bonded.isChecked = contains(Property.Type.BONDED)
- cb_read_mitm.isChecked = contains(Property.Type.AUTHENTICATED)
+ binding.propertiesContent.cbReadBonded.isChecked = contains(Property.Type.BONDED)
+ binding.propertiesContent.cbReadMitm.isChecked =
+ contains(Property.Type.AUTHENTICATED)
}
this[Property.WRITE]?.apply {
- cb_write_bonded.isChecked = contains(Property.Type.BONDED)
- cb_write_mitm.isChecked = contains(Property.Type.AUTHENTICATED)
+ binding.propertiesContent.cbWriteBonded.isChecked = contains(Property.Type.BONDED)
+ binding.propertiesContent.cbWriteMitm.isChecked =
+ contains(Property.Type.AUTHENTICATED)
return
}
this[Property.WRITE_WITHOUT_RESPONSE]?.apply {
- cb_write_bonded.isChecked = contains(Property.Type.BONDED)
- cb_write_mitm.isChecked = contains(Property.Type.AUTHENTICATED)
+ binding.propertiesContent.cbWriteBonded.isChecked = contains(Property.Type.BONDED)
+ binding.propertiesContent.cbWriteMitm.isChecked =
+ contains(Property.Type.AUTHENTICATED)
return
}
this[Property.RELIABLE_WRITE]?.apply {
- cb_write_bonded.isChecked = contains(Property.Type.BONDED)
- cb_write_mitm.isChecked = contains(Property.Type.AUTHENTICATED)
+ binding.propertiesContent.cbWriteBonded.isChecked = contains(Property.Type.BONDED)
+ binding.propertiesContent.cbWriteMitm.isChecked =
+ contains(Property.Type.AUTHENTICATED)
return
}
}
@@ -104,184 +122,221 @@ class CharacteristicDialog(val listener: CharacteristicChangeListener, val chara
private fun prepopulateInitialValue() {
when (characteristic.value?.type) {
Value.Type.USER -> {
- sp_initial_value.setSelection(POSITION_INITIAL_VALUE_EMPTY)
+ binding.initialValue.spInitialValue.setSelection(POSITION_INITIAL_VALUE_EMPTY)
}
+
Value.Type.UTF_8 -> {
- sp_initial_value.setSelection(POSITION_INITIAL_VALUE_TEXT)
- et_initial_value_text.setText(characteristic.value?.value)
+ binding.initialValue.spInitialValue.setSelection(POSITION_INITIAL_VALUE_TEXT)
+ binding.initialValue.etInitialValueText.setText(characteristic.value?.value)
}
+
Value.Type.HEX -> {
- sp_initial_value.setSelection(POSITION_INITIAL_VALUE_HEX)
- et_initial_value_hex.setText(characteristic.value?.value)
+ binding.initialValue.spInitialValue.setSelection(POSITION_INITIAL_VALUE_HEX)
+ binding.initialValue.etInitialValueHex.setText(characteristic.value?.value)
}
+
else -> Unit
}
}
private fun setCharacteristicState() {
- characteristic.name = actv_characteristic_name.text.toString()
- characteristic.uuid = Uuid(actv_characteristic_uuid.text.toString())
+ characteristic.name = binding.actvCharacteristicName.text.toString()
+ characteristic.uuid = Uuid(binding.actvCharacteristicUuid.text.toString())
setPropertiesState()
setInitialValue()
}
private fun setPropertiesState() {
characteristic.properties.clear()
- if (sw_read.isChecked) characteristic.properties[Property.READ] = getSelectedReadTypes()
- if (sw_write.isChecked) characteristic.properties[Property.WRITE] = getSelectedWriteTypes()
- if (sw_write_without_resp.isChecked) characteristic.properties[Property.WRITE_WITHOUT_RESPONSE] = getSelectedWriteTypes()
- if (sw_reliable_write.isChecked) characteristic.properties[Property.RELIABLE_WRITE] = getSelectedWriteTypes()
- if (sw_notify.isChecked) characteristic.properties[Property.NOTIFY] = hashSetOf()
- if (sw_indicate.isChecked) characteristic.properties[Property.INDICATE] = hashSetOf()
+ if (binding.propertiesContent.swRead.isChecked) characteristic.properties[Property.READ] =
+ getSelectedReadTypes()
+ if (binding.propertiesContent.swWrite.isChecked) characteristic.properties[Property.WRITE] =
+ getSelectedWriteTypes()
+ if (binding.propertiesContent.swWriteWithoutResp.isChecked) characteristic.properties[Property.WRITE_WITHOUT_RESPONSE] =
+ getSelectedWriteTypes()
+ if (binding.propertiesContent.swReliableWrite.isChecked) characteristic.properties[Property.RELIABLE_WRITE] =
+ getSelectedWriteTypes()
+ if (binding.propertiesContent.swNotify.isChecked) characteristic.properties[Property.NOTIFY] =
+ hashSetOf()
+ if (binding.propertiesContent.swIndicate.isChecked) characteristic.properties[Property.INDICATE] =
+ hashSetOf()
handlePropertiesUsingDescriptors()
}
private fun handlePropertiesUsingDescriptors() {
- if (sw_reliable_write.isChecked) setReliableWritePropertyDescriptor()
+ if (binding.propertiesContent.swReliableWrite.isChecked) setReliableWritePropertyDescriptor()
else removeReliableWritePropertyDescriptor()
- if (sw_indicate.isChecked || sw_notify.isChecked) setIndicateOrNotifyPropertyDescriptor()
+ if (binding.propertiesContent.swIndicate.isChecked || binding.propertiesContent.swNotify.isChecked) setIndicateOrNotifyPropertyDescriptor()
else removeIndicateOrNotifyPropertyDescriptor()
}
private fun setReliableWritePropertyDescriptor() {
- val result = characteristic.descriptors.filter { it.name == GattUtils.getReliableWriteDescriptor().name && it.isPredefined }
+ val result =
+ characteristic.descriptors.filter { it.name == GattUtils.getReliableWriteDescriptor().name && it.isPredefined }
if (result.isEmpty()) {
characteristic.descriptors.add(GattUtils.getReliableWriteDescriptor())
}
}
private fun removeReliableWritePropertyDescriptor() {
- val descriptor = characteristic.descriptors.find { it.name == GattUtils.getReliableWriteDescriptor().name && it.isPredefined }
+ val descriptor =
+ characteristic.descriptors.find { it.name == GattUtils.getReliableWriteDescriptor().name && it.isPredefined }
characteristic.descriptors.remove(descriptor)
}
private fun setIndicateOrNotifyPropertyDescriptor() {
- val result = characteristic.descriptors.filter { it.name == GattUtils.getIndicateOrNotifyDescriptor().name && it.isPredefined }
+ val result =
+ characteristic.descriptors.filter { it.name == GattUtils.getIndicateOrNotifyDescriptor().name && it.isPredefined }
if (result.isEmpty()) {
characteristic.descriptors.add(GattUtils.getIndicateOrNotifyDescriptor())
}
}
private fun removeIndicateOrNotifyPropertyDescriptor() {
- val descriptor = characteristic.descriptors.find { it.name == GattUtils.getIndicateOrNotifyDescriptor().name && it.isPredefined }
+ val descriptor =
+ characteristic.descriptors.find { it.name == GattUtils.getIndicateOrNotifyDescriptor().name && it.isPredefined }
characteristic.descriptors.remove(descriptor)
}
private fun getSelectedReadTypes(): HashSet {
return hashSetOf().apply {
- if (cb_read_bonded.isChecked) add(Property.Type.BONDED)
- if (cb_read_mitm.isChecked) add(Property.Type.AUTHENTICATED)
+ if (binding.propertiesContent.cbReadBonded.isChecked) add(Property.Type.BONDED)
+ if (binding.propertiesContent.cbReadMitm.isChecked) add(Property.Type.AUTHENTICATED)
}
}
private fun getSelectedWriteTypes(): HashSet {
return hashSetOf().apply {
- if (cb_write_bonded.isChecked) add(Property.Type.BONDED)
- if (cb_write_mitm.isChecked) add(Property.Type.AUTHENTICATED)
+ if (binding.propertiesContent.cbWriteBonded.isChecked) add(Property.Type.BONDED)
+ if (binding.propertiesContent.cbWriteMitm.isChecked) add(Property.Type.AUTHENTICATED)
}
}
private fun setInitialValue() {
- when (sp_initial_value.selectedItemPosition) {
+ when (binding.initialValue.spInitialValue.selectedItemPosition) {
POSITION_INITIAL_VALUE_EMPTY -> {
characteristic.value = Value(
- value = "",
- type = Value.Type.USER
+ value = "",
+ type = Value.Type.USER
)
}
+
POSITION_INITIAL_VALUE_TEXT -> {
characteristic.value = Value(
- value = et_initial_value_text.text.toString(),
- type = Value.Type.UTF_8,
- length = et_initial_value_text.text.length
+ value = binding.initialValue.etInitialValueText.text.toString(),
+ type = Value.Type.UTF_8,
+ length = binding.initialValue.etInitialValueText.text.length
)
}
+
POSITION_INITIAL_VALUE_HEX -> {
characteristic.value = Value(
- value = et_initial_value_hex.text.toString(),
- type = Value.Type.HEX,
- length = et_initial_value_hex.length() / 2
+ value = binding.initialValue.etInitialValueHex.text.toString(),
+ type = Value.Type.HEX,
+ length = binding.initialValue.etInitialValueHex.length() / 2
)
}
}
}
private fun handleNameChanges() {
- actv_characteristic_name.addTextChangedListener(object : TextWatcher {
+ binding.actvCharacteristicName.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- btn_save.isEnabled = isInputValid()
+ binding.btnSave.isEnabled = isInputValid()
}
})
}
private fun handleUuidChanges() {
- actv_characteristic_uuid.addTextChangedListener(object : TextWatcher {
+ binding.actvCharacteristicUuid.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val len = s?.length
- if ((len == 8 || len == 13 || len == 18 || len == 23) && count > before) actv_characteristic_uuid.append("-")
- btn_save.isEnabled = isInputValid()
+ if ((len == 8 || len == 13 || len == 18 || len == 23) && count > before) binding.actvCharacteristicUuid.append(
+ "-"
+ )
+ binding.btnSave.isEnabled = isInputValid()
}
})
}
private fun handleInitialValueEditTextChanges() {
- et_initial_value_text.addTextChangedListener(object : TextWatcher {
+ binding.initialValue.etInitialValueText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- btn_save.isEnabled = isInputValid()
+ binding.btnSave.isEnabled = isInputValid()
}
})
- et_initial_value_hex.addTextChangedListener(object : TextWatcher {
+ binding.initialValue.etInitialValueHex.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- btn_save.isEnabled = isInputValid()
+ binding.btnSave.isEnabled = isInputValid()
}
})
}
private fun isAnyPropertyChecked(): Boolean {
- return sw_read.isChecked ||
- sw_write.isChecked ||
- sw_write_without_resp.isChecked ||
- sw_reliable_write.isChecked ||
- sw_notify.isChecked ||
- sw_indicate.isChecked
+ return binding.propertiesContent.swRead.isChecked ||
+ binding.propertiesContent.swWrite.isChecked ||
+ binding.propertiesContent.swWriteWithoutResp.isChecked ||
+ binding.propertiesContent.swReliableWrite.isChecked ||
+ binding.propertiesContent.swNotify.isChecked ||
+ binding.propertiesContent.swIndicate.isChecked
}
private fun handlePropertyStateChanges() {
- sw_read.setOnCheckedChangeListener { _, _ ->
- btn_save.isEnabled = isInputValid()
- setPropertyParametersState(sw_read.isChecked, cb_read_bonded, cb_read_mitm)
+ binding.propertiesContent.swRead.setOnCheckedChangeListener { _, _ ->
+ binding.btnSave.isEnabled = isInputValid()
+ setPropertyParametersState(
+ binding.propertiesContent.swRead.isChecked,
+ binding.propertiesContent.cbReadBonded,
+ binding.propertiesContent.cbReadMitm
+ )
}
- sw_write.setOnCheckedChangeListener { _, _ ->
- btn_save.isEnabled = isInputValid()
- setPropertyParametersState(sw_write.isChecked || sw_write_without_resp.isChecked || sw_reliable_write.isChecked, cb_write_bonded, cb_write_mitm)
+ binding.propertiesContent.swWrite.setOnCheckedChangeListener { _, _ ->
+ binding.btnSave.isEnabled = isInputValid()
+ setPropertyParametersState(
+ binding.propertiesContent.swWrite.isChecked || binding.propertiesContent.swWriteWithoutResp.isChecked || binding.propertiesContent.swReliableWrite.isChecked,
+ binding.propertiesContent.cbWriteBonded,
+ binding.propertiesContent.cbWriteMitm
+ )
}
- sw_write_without_resp.setOnCheckedChangeListener { _, _ ->
- btn_save.isEnabled = isInputValid()
- setPropertyParametersState(sw_write.isChecked || sw_write_without_resp.isChecked || sw_reliable_write.isChecked, cb_write_bonded, cb_write_mitm)
+ binding.propertiesContent.swWriteWithoutResp.setOnCheckedChangeListener { _, _ ->
+ binding.btnSave.isEnabled = isInputValid()
+ setPropertyParametersState(
+ binding.propertiesContent.swWrite.isChecked || binding.propertiesContent.swWriteWithoutResp.isChecked || binding.propertiesContent.swReliableWrite.isChecked,
+ binding.propertiesContent.cbWriteBonded,
+ binding.propertiesContent.cbWriteMitm
+ )
}
- sw_reliable_write.setOnCheckedChangeListener { _, _ ->
- btn_save.isEnabled = isInputValid()
- setPropertyParametersState(sw_write.isChecked || sw_write_without_resp.isChecked || sw_reliable_write.isChecked, cb_write_bonded, cb_write_mitm)
+ binding.propertiesContent.swReliableWrite.setOnCheckedChangeListener { _, _ ->
+ binding.btnSave.isEnabled = isInputValid()
+ setPropertyParametersState(
+ binding.propertiesContent.swWrite.isChecked || binding.propertiesContent.swWriteWithoutResp.isChecked || binding.propertiesContent.swReliableWrite.isChecked,
+ binding.propertiesContent.cbWriteBonded,
+ binding.propertiesContent.cbWriteMitm
+ )
}
- sw_notify.setOnCheckedChangeListener { _, _ ->
- btn_save.isEnabled = isInputValid()
+ binding.propertiesContent.swNotify.setOnCheckedChangeListener { _, _ ->
+ binding.btnSave.isEnabled = isInputValid()
}
- sw_indicate.setOnCheckedChangeListener { _, _ ->
- btn_save.isEnabled = isInputValid()
+ binding.propertiesContent.swIndicate.setOnCheckedChangeListener { _, _ ->
+ binding.btnSave.isEnabled = isInputValid()
}
}
- private fun setPropertyParametersState(switchState: Boolean, cbBonded: CheckBox, cbMitm: CheckBox) {
+ private fun setPropertyParametersState(
+ switchState: Boolean,
+ cbBonded: CheckBox,
+ cbMitm: CheckBox
+ ) {
cbBonded.isEnabled = switchState
cbMitm.isEnabled = switchState
if (!switchState) {
@@ -292,21 +347,23 @@ class CharacteristicDialog(val listener: CharacteristicChangeListener, val chara
private fun isInputValid(): Boolean {
return isAnyPropertyChecked()
- && actv_characteristic_name.text.toString().isNotEmpty()
- && isUuidValid(actv_characteristic_uuid.text.toString())
+ && binding.actvCharacteristicName.text.toString().isNotEmpty()
+ && isUuidValid(binding.actvCharacteristicUuid.text.toString())
&& isInitialValueValid()
}
private fun isInitialValueValid(): Boolean {
- when (sp_initial_value.selectedItemPosition) {
+ when (binding.initialValue.spInitialValue.selectedItemPosition) {
POSITION_INITIAL_VALUE_EMPTY -> {
return true
}
+
POSITION_INITIAL_VALUE_TEXT -> {
- return et_initial_value_text.text.toString().isNotEmpty()
+ return binding.initialValue.etInitialValueText.text.toString().isNotEmpty()
}
+
POSITION_INITIAL_VALUE_HEX -> {
- return Validator.isHexValid(et_initial_value_hex.text.toString())
+ return Validator.isHexValid(binding.initialValue.etInitialValueHex.text.toString())
}
}
return true
@@ -317,55 +374,71 @@ class CharacteristicDialog(val listener: CharacteristicChangeListener, val chara
}
private fun initACTV(actv: AutoCompleteTextView, searchMode: SearchMode) {
- val adapter = Characteristic16BitAdapter(requireContext(), GattUtils.get16BitCharacteristics(), searchMode)
+ val adapter = Characteristic16BitAdapter(
+ requireContext(),
+ GattUtils.get16BitCharacteristics(),
+ searchMode
+ )
actv.setAdapter(adapter)
actv.setOnItemClickListener { _, _, position, _ ->
val characteristic = adapter.getItem(position)
- actv_characteristic_name.setText(characteristic?.name)
- actv_characteristic_uuid.setText(characteristic?.getIdentifierAsString())
+ binding.actvCharacteristicName.setText(characteristic?.name)
+ binding.actvCharacteristicUuid.setText(characteristic?.getIdentifierAsString())
actv.setSelection(actv.length())
hideKeyboard()
}
}
private fun initInitialValueSpinner() {
- val adapter = ArrayAdapter(requireContext(), R.layout.spinner_item_layout, resources.getStringArray(R.array.gatt_configurator_initial_value))
+ val adapter = ArrayAdapter(
+ requireContext(),
+ R.layout.spinner_item_layout,
+ resources.getStringArray(R.array.gatt_configurator_initial_value)
+ )
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item_layout)
- sp_initial_value.adapter = adapter
+ binding.initialValue.spInitialValue.adapter = adapter
handleInitialValueSelection()
}
private fun handleInitialValueSelection() {
- sp_initial_value.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
- override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
- btn_save.isEnabled = isInputValid()
- et_initial_value_text.visibility = if (position == POSITION_INITIAL_VALUE_TEXT) View.VISIBLE else View.GONE
- ll_initial_value_hex.visibility = if (position == POSITION_INITIAL_VALUE_HEX) View.VISIBLE else View.GONE
+ binding.initialValue.spInitialValue.onItemSelectedListener =
+ object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ binding.btnSave.isEnabled = isInputValid()
+ binding.initialValue.etInitialValueText.visibility =
+ if (position == POSITION_INITIAL_VALUE_TEXT) View.VISIBLE else View.GONE
+ binding.initialValue.llInitialValueHex.visibility =
+ if (position == POSITION_INITIAL_VALUE_HEX) View.VISIBLE else View.GONE
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {
+ }
}
-
- override fun onNothingSelected(parent: AdapterView<*>?) {
- }
- }
}
private fun clearAllFields() {
- actv_characteristic_name.setText("")
- actv_characteristic_uuid.setText("")
- sw_read.isChecked = true
- sw_write.isChecked = false
- sw_write_without_resp.isChecked = false
- sw_reliable_write.isChecked = false
- sw_notify.isChecked = false
- sw_indicate.isChecked = false
- cb_read_bonded.isChecked = false
- cb_read_mitm.isChecked = false
- cb_write_bonded.isChecked = false
- cb_write_mitm.isChecked = false
- sp_initial_value.setSelection(0)
- et_initial_value_text.setText("")
- et_initial_value_hex.setText("")
+ binding.actvCharacteristicName.setText("")
+ binding.actvCharacteristicUuid.setText("")
+ binding.propertiesContent.swRead.isChecked = true
+ binding.propertiesContent.swWrite.isChecked = false
+ binding.propertiesContent.swWriteWithoutResp.isChecked = false
+ binding.propertiesContent.swReliableWrite.isChecked = false
+ binding.propertiesContent.swNotify.isChecked = false
+ binding.propertiesContent.swIndicate.isChecked = false
+ binding.propertiesContent.cbReadBonded.isChecked = false
+ binding.propertiesContent.cbReadMitm.isChecked = false
+ binding.propertiesContent.cbWriteBonded.isChecked = false
+ binding.propertiesContent.cbWriteMitm.isChecked = false
+ binding.initialValue.spInitialValue.setSelection(0)
+ binding.initialValue.etInitialValueText.setText("")
+ binding.initialValue.etInitialValueHex.setText("")
}
interface CharacteristicChangeListener {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/DescriptorDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/DescriptorDialog.kt
index 99829dde..9a19cb5a 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/DescriptorDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/DescriptorDialog.kt
@@ -13,25 +13,36 @@ import android.widget.CheckBox
import androidx.appcompat.widget.SwitchCompat
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
+import com.siliconlabs.bledemo.databinding.DialogGattServerDescriptorBinding
import com.siliconlabs.bledemo.features.configure.gatt_configurator.adapters.Descriptor16BitAdapter
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.*
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.GattUtils
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.Validator
-import kotlinx.android.synthetic.main.dialog_gatt_server_descriptor.*
-import kotlinx.android.synthetic.main.dialog_add_descriptor_properties_content.*
-import kotlinx.android.synthetic.main.gatt_configurator_initial_value.*
-class DescriptorDialog(val listener: DescriptorChangeListener, val descriptor: Descriptor = Descriptor()) : BaseDialogFragment() {
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_gatt_server_descriptor, container, false)
+//import kotlinx.android.synthetic.main.dialog_gatt_server_descriptor.*
+//import kotlinx.android.synthetic.main.dialog_add_descriptor_properties_content.*
+//import kotlinx.android.synthetic.main.gatt_configurator_initial_value.*
+
+class DescriptorDialog(
+ val listener: DescriptorChangeListener,
+ val descriptor: Descriptor = Descriptor()
+) : BaseDialogFragment() {
+ private lateinit var binding: DialogGattServerDescriptorBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogGattServerDescriptorBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- initACTV(actv_descriptor_name, SearchMode.BY_NAME)
- initACTV(actv_descriptor_uuid, SearchMode.BY_UUID)
+ initACTV(binding.actvDescriptorName, SearchMode.BY_NAME)
+ initACTV(binding.actvDescriptorUuid, SearchMode.BY_UUID)
initInitialValueSpinner()
handleClickEvents()
@@ -43,24 +54,24 @@ class DescriptorDialog(val listener: DescriptorChangeListener, val descriptor: D
}
private fun handleClickEvents() {
- btn_save.setOnClickListener {
+ binding.btnSave.setOnClickListener {
setDescriptorState()
listener.onDescriptorChanged(descriptor)
dismiss()
}
- btn_clear.setOnClickListener {
+ binding.btnClear.setOnClickListener {
clearAllFields()
}
- btn_cancel.setOnClickListener {
+ binding.btnCancel.setOnClickListener {
dismiss()
}
}
private fun prepopulateFields() {
- actv_descriptor_name.setText(descriptor.name)
- actv_descriptor_uuid.setText(descriptor.uuid?.uuid)
+ binding.actvDescriptorName.setText(descriptor.name)
+ binding.actvDescriptorUuid.setText(descriptor.uuid?.uuid)
prepopulateProperties()
prepopulatePropertyTypes()
prepopulateInitialValue()
@@ -68,21 +79,24 @@ class DescriptorDialog(val listener: DescriptorChangeListener, val descriptor: D
private fun prepopulateProperties() {
descriptor.properties.apply {
- sw_read.isChecked = containsKey(Property.READ)
- sw_write.isChecked = containsKey(Property.WRITE)
+
+ binding.propertiesContent.swRead.isChecked = containsKey(Property.READ)
+ binding.propertiesContent.swWrite.isChecked = containsKey(Property.WRITE)
}
}
private fun prepopulatePropertyTypes() {
descriptor.properties.apply {
this[Property.READ]?.apply {
- cb_read_bonded.isChecked = contains(Property.Type.BONDED)
- cb_read_mitm.isChecked = contains(Property.Type.AUTHENTICATED)
+
+ binding.propertiesContent.cbReadBonded.isChecked = contains(Property.Type.BONDED)
+ binding.propertiesContent.cbReadMitm.isChecked = contains(Property.Type.AUTHENTICATED)
}
this[Property.WRITE]?.apply {
- cb_write_bonded.isChecked = contains(Property.Type.BONDED)
- cb_write_mitm.isChecked = contains(Property.Type.AUTHENTICATED)
+
+ binding.propertiesContent.cbWriteBonded.isChecked = contains(Property.Type.BONDED)
+ binding.propertiesContent.cbWriteMitm.isChecked = contains(Property.Type.AUTHENTICATED)
}
}
}
@@ -90,62 +104,81 @@ class DescriptorDialog(val listener: DescriptorChangeListener, val descriptor: D
private fun prepopulateInitialValue() {
when (descriptor.value?.type) {
Value.Type.USER -> {
- sp_initial_value.setSelection(POSITION_INITIAL_VALUE_EMPTY)
+
+ binding.initialValue.spInitialValue.setSelection(POSITION_INITIAL_VALUE_EMPTY)
}
+
Value.Type.UTF_8 -> {
- sp_initial_value.setSelection(POSITION_INITIAL_VALUE_TEXT)
- et_initial_value_text.setText(descriptor.value?.value)
+
+ binding.initialValue.spInitialValue.setSelection(POSITION_INITIAL_VALUE_TEXT)
+ binding.initialValue.etInitialValueText.setText(descriptor.value?.value)
}
+
Value.Type.HEX -> {
- sp_initial_value.setSelection(POSITION_INITIAL_VALUE_HEX)
- et_initial_value_hex.setText(descriptor.value?.value)
+
+ binding.initialValue.spInitialValue.setSelection(POSITION_INITIAL_VALUE_HEX)
+ binding.initialValue.etInitialValueHex.setText(descriptor.value?.value)
}
+
else -> Unit
}
}
private fun isInitialValueValid(): Boolean {
- when (sp_initial_value.selectedItemPosition) {
+ when (binding.initialValue.spInitialValue.selectedItemPosition) {
POSITION_INITIAL_VALUE_EMPTY -> {
return true
}
+
POSITION_INITIAL_VALUE_TEXT -> {
- return et_initial_value_text.text.toString().isNotEmpty()
+ return binding.initialValue.etInitialValueText.text.toString().isNotEmpty()
}
+
POSITION_INITIAL_VALUE_HEX -> {
- return Validator.isHexValid(et_initial_value_hex.text.toString())
+ return Validator.isHexValid(binding.initialValue.etInitialValueHex.text.toString())
}
}
return true
}
private fun initACTV(actv: AutoCompleteTextView, searchMode: SearchMode) {
- val adapter = Descriptor16BitAdapter(requireContext(), GattUtils.get16BitDescriptors(), searchMode)
+ val adapter =
+ Descriptor16BitAdapter(requireContext(), GattUtils.get16BitDescriptors(), searchMode)
actv.setAdapter(adapter)
actv.setOnItemClickListener { _, _, position, _ ->
val descriptor = adapter.getItem(position)
- actv_descriptor_name.setText(descriptor?.name)
- actv_descriptor_uuid.setText(descriptor?.getIdentifierAsString())
+ binding.actvDescriptorName.setText(descriptor?.name)
+ binding.actvDescriptorUuid.setText(descriptor?.getIdentifierAsString())
actv.setSelection(actv.length())
hideKeyboard()
}
}
private fun initInitialValueSpinner() {
- val adapter = ArrayAdapter(requireContext(), R.layout.spinner_item_layout, resources.getStringArray(R.array.gatt_configurator_initial_value))
+ val adapter = ArrayAdapter(
+ requireContext(),
+ R.layout.spinner_item_layout,
+ resources.getStringArray(R.array.gatt_configurator_initial_value)
+ )
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item_layout)
- sp_initial_value.adapter = adapter
+ binding.initialValue.spInitialValue.adapter = adapter
handleInitialValueSelection()
}
private fun handleInitialValueSelection() {
- sp_initial_value.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
- override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
- btn_save.isEnabled = isInputValid()
- et_initial_value_text.visibility = if (position == 1) View.VISIBLE else View.GONE
- ll_initial_value_hex.visibility = if (position == 2) View.VISIBLE else View.GONE
+ binding.initialValue.spInitialValue.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+
+ binding.btnSave.isEnabled = isInputValid()
+ binding.initialValue.etInitialValueText.visibility = if (position == 1) View.VISIBLE else View.GONE
+ binding.initialValue.llInitialValueHex.visibility = if (position == 2) View.VISIBLE else View.GONE
}
override fun onNothingSelected(parent: AdapterView<*>?) {
@@ -154,120 +187,133 @@ class DescriptorDialog(val listener: DescriptorChangeListener, val descriptor: D
}
private fun handleNameChanges() {
- actv_descriptor_name.addTextChangedListener(object : TextWatcher {
+ binding.actvDescriptorName.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- btn_save.isEnabled = isInputValid()
+ binding.btnSave.isEnabled = isInputValid()
}
})
}
private fun handleUuidChanges() {
- actv_descriptor_uuid.addTextChangedListener(object : TextWatcher {
+ binding.actvDescriptorUuid.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val len = s?.length
- if ((len == 8 || len == 13 || len == 18 || len == 23) && count > before) actv_descriptor_uuid.append("-")
- btn_save.isEnabled = isInputValid()
+ if ((len == 8 || len == 13 || len == 18 || len == 23) && count > before) binding.actvDescriptorUuid.append(
+ "-"
+ )
+ binding.btnSave.isEnabled = isInputValid()
}
})
}
private fun handleInitialValueEditTextChanges() {
- et_initial_value_text.addTextChangedListener(object : TextWatcher {
+ binding.initialValue.etInitialValueText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- btn_save.isEnabled = isInputValid()
+ binding.btnSave.isEnabled = isInputValid()
}
})
- et_initial_value_hex.addTextChangedListener(object : TextWatcher {
+ binding.initialValue.etInitialValueHex.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- btn_save.isEnabled = isInputValid()
+ binding.btnSave.isEnabled = isInputValid()
}
})
}
private fun handlePropertyStateChanges() {
- sw_read.setOnCheckedChangeListener { _, _ ->
- btn_save.isEnabled = isInputValid()
- setPropertyParametersState(sw_read, cb_read_bonded, cb_read_mitm)
+ binding.propertiesContent.swRead.setOnCheckedChangeListener { _, _ ->
+ binding.btnSave.isEnabled = isInputValid()
+ setPropertyParametersState(
+ binding.propertiesContent.swRead,
+ binding.propertiesContent.cbReadBonded,
+ binding.propertiesContent.cbReadMitm
+ )
}
- sw_write.setOnCheckedChangeListener { _, _ ->
- btn_save.isEnabled = isInputValid()
- setPropertyParametersState(sw_write, cb_write_bonded, cb_write_mitm)
+ binding.propertiesContent.swWrite.setOnCheckedChangeListener { _, _ ->
+ binding.btnSave.isEnabled = isInputValid()
+ setPropertyParametersState(binding.propertiesContent.swWrite, binding.propertiesContent.cbWriteBonded, binding.propertiesContent.cbWriteMitm)
}
}
- private fun setPropertyParametersState(switch: SwitchCompat, cbBonded: CheckBox, cbMitm: CheckBox) {
+ private fun setPropertyParametersState(
+ switch: SwitchCompat,
+ cbBonded: CheckBox,
+ cbMitm: CheckBox
+ ) {
cbBonded.isEnabled = switch.isChecked
cbMitm.isEnabled = switch.isChecked
- if(!switch.isChecked) {
+ if (!switch.isChecked) {
cbBonded.isChecked = false
cbMitm.isChecked = false
}
}
private fun setDescriptorState() {
- descriptor.name = actv_descriptor_name.text.toString()
- descriptor.uuid = Uuid(actv_descriptor_uuid.text.toString())
+ descriptor.name = binding.actvDescriptorName.text.toString()
+ descriptor.uuid = Uuid(binding.actvDescriptorUuid.text.toString())
setPropertiesState()
setInitialValue()
}
private fun setPropertiesState() {
descriptor.properties.clear()
- if (sw_read.isChecked) descriptor.properties[Property.READ] = getSelectedReadTypes()
- if (sw_write.isChecked) descriptor.properties[Property.WRITE] = getSelectedWriteTypes()
+ if (binding.propertiesContent.swRead.isChecked) descriptor.properties[Property.READ] =
+ getSelectedReadTypes()
+ if (binding.propertiesContent.swWrite.isChecked) descriptor.properties[Property.WRITE] = getSelectedWriteTypes()
}
private fun getSelectedReadTypes(): HashSet {
return hashSetOf().apply {
- if (cb_read_bonded.isChecked) add(Property.Type.BONDED)
- if (cb_read_mitm.isChecked) add(Property.Type.AUTHENTICATED)
+ if ( binding.propertiesContent.cbReadBonded.isChecked) add(Property.Type.BONDED)
+ if (binding.propertiesContent.cbReadMitm.isChecked) add(Property.Type.AUTHENTICATED)
}
}
private fun getSelectedWriteTypes(): HashSet {
return hashSetOf().apply {
- if (cb_write_bonded.isChecked) add(Property.Type.BONDED)
- if (cb_write_mitm.isChecked) add(Property.Type.AUTHENTICATED)
+ if (binding.propertiesContent.cbWriteBonded.isChecked) add(Property.Type.BONDED)
+ if (binding.propertiesContent.cbWriteMitm.isChecked) add(Property.Type.AUTHENTICATED)
}
}
private fun setInitialValue() {
- when (sp_initial_value.selectedItemPosition) {
+ when (binding.initialValue.spInitialValue.selectedItemPosition) {
POSITION_INITIAL_VALUE_EMPTY -> {
descriptor.value = Value(
- value = "",
- type = Value.Type.USER
+ value = "",
+ type = Value.Type.USER
)
}
+
POSITION_INITIAL_VALUE_TEXT -> {
descriptor.value = Value(
- value = et_initial_value_text.text.toString(),
- type = Value.Type.UTF_8,
- length = et_initial_value_text.text.length
+ value = binding.initialValue.etInitialValueText.text.toString(),
+ type = Value.Type.UTF_8,
+ length = binding.initialValue.etInitialValueText.text.length
)
}
+
POSITION_INITIAL_VALUE_HEX -> {
descriptor.value = Value(
- value = et_initial_value_hex.text.toString(),
- type = Value.Type.HEX,
- length = et_initial_value_text.length() / 2
+ value = binding.initialValue.etInitialValueHex.text.toString(),
+ type = Value.Type.HEX,
+ length = binding.initialValue.etInitialValueText.length() / 2
)
}
}
}
private fun isAnyPropertyChecked(): Boolean {
- return sw_read.isChecked ||
- sw_write.isChecked
+ return binding.propertiesContent.swRead.isChecked ||
+ binding.propertiesContent.swWrite.isChecked
}
private fun isUuidValid(uuid: String): Boolean {
@@ -276,23 +322,23 @@ class DescriptorDialog(val listener: DescriptorChangeListener, val descriptor: D
private fun isInputValid(): Boolean {
return isAnyPropertyChecked()
- && actv_descriptor_name.text.toString().isNotEmpty()
- && isUuidValid(actv_descriptor_uuid.text.toString())
+ && binding.actvDescriptorName.text.toString().isNotEmpty()
+ && isUuidValid(binding.actvDescriptorUuid.text.toString())
&& isInitialValueValid()
}
private fun clearAllFields() {
- actv_descriptor_name.setText("")
- actv_descriptor_uuid.setText("")
- sw_read.isChecked = true
- sw_write.isChecked = false
- cb_read_bonded.isChecked = false
- cb_read_mitm.isChecked = false
- cb_write_bonded.isChecked = false
- cb_write_mitm.isChecked = false
- sp_initial_value.setSelection(0)
- et_initial_value_text.setText("")
- et_initial_value_hex.setText("")
+ binding.actvDescriptorName.setText("")
+ binding.actvDescriptorUuid.setText("")
+ binding.propertiesContent.swRead.isChecked = true
+ binding.propertiesContent.swWrite.isChecked = false
+ binding.propertiesContent.cbReadBonded.isChecked = false
+ binding.propertiesContent.cbReadMitm.isChecked = false
+ binding.propertiesContent.cbWriteBonded.isChecked = false
+ binding.propertiesContent.cbWriteMitm.isChecked = false
+ binding.initialValue.spInitialValue.setSelection(0)
+ binding.initialValue.etInitialValueText.setText("")
+ binding.initialValue.etInitialValueHex.setText("")
}
interface DescriptorChangeListener {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/LeaveGattServerConfigDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/LeaveGattServerConfigDialog.kt
index 62754342..63572967 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/LeaveGattServerConfigDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/LeaveGattServerConfigDialog.kt
@@ -6,33 +6,41 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
+import com.siliconlabs.bledemo.databinding.DialogInfoOkCancelBinding
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.GattConfiguratorStorage
-import kotlinx.android.synthetic.main.dialog_info_ok_cancel.*
-class LeaveGattServerConfigDialog(val callback: Callback) : BaseDialogFragment() {
+//import kotlinx.android.synthetic.main.dialog_info_ok_cancel.*
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_info_ok_cancel, container, false)
+class LeaveGattServerConfigDialog(val callback: Callback) : BaseDialogFragment() {
+ private lateinit var binding: DialogInfoOkCancelBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogInfoOkCancelBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- tv_dialog_title.text = context?.getString(R.string.title_unsaved_changes)
- tv_dialog_content.text = context?.getString(R.string.gatt_configurator_leave_config_dialog_content)
+ binding.tvDialogTitle.text = context?.getString(R.string.title_unsaved_changes)
+ binding.tvDialogContent.text =
+ context?.getString(R.string.gatt_configurator_leave_config_dialog_content)
- btn_ok.text = context?.getString(R.string.button_yes)
- btn_cancel.text = context?.getString(R.string.button_no)
+ binding.btnOk.text = context?.getString(R.string.button_yes)
+ binding.btnCancel.text = context?.getString(R.string.button_no)
- btn_ok.setOnClickListener {
- if (cb_dont_show_again.isChecked) GattConfiguratorStorage(requireContext())
- .setShouldDisplayLeaveGattServerConfigDialog(false)
+ binding.btnOk.setOnClickListener {
+ if (binding.cbDontShowAgain.isChecked
+ ) GattConfiguratorStorage(requireContext())
+ .setShouldDisplayLeaveGattServerConfigDialog(false)
callback.onYesClicked()
dismiss()
}
- btn_cancel.setOnClickListener {
+ binding.btnCancel.setOnClickListener {
dismiss()
callback.onNoClicked()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/ServiceDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/ServiceDialog.kt
index 7f2d888f..5394bdc6 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/ServiceDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/dialogs/ServiceDialog.kt
@@ -13,26 +13,36 @@ import android.widget.AutoCompleteTextView
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.bluetooth.parsing.Engine
+import com.siliconlabs.bledemo.databinding.DialogGattServerDescriptorBinding
+import com.siliconlabs.bledemo.databinding.DialogGattServerServiceBinding
import com.siliconlabs.bledemo.utils.UuidUtils
import com.siliconlabs.bledemo.features.configure.gatt_configurator.adapters.Service16BitAdapter
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.*
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.GattUtils
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.Validator
-import kotlinx.android.synthetic.main.dialog_gatt_server_service.*
+//import kotlinx.android.synthetic.main.dialog_gatt_server_service.*
import java.util.*
-class ServiceDialog(val listener: ServiceChangeListener, var service: Service = Service()) : BaseDialogFragment() {
+class ServiceDialog(val listener: ServiceChangeListener, var service: Service = Service()) :
+ BaseDialogFragment() {
private val predefinedServices: List = GattUtils.get16BitServices()
+ private lateinit var binding: DialogGattServerServiceBinding
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_gatt_server_service, container, false)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogGattServerServiceBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- initACTV(actv_service_name, SearchMode.BY_NAME)
- initACTV(actv_service_uuid, SearchMode.BY_UUID)
+
+ initACTV(binding.actvServiceName, SearchMode.BY_NAME)
+ initACTV(binding.actvServiceUuid, SearchMode.BY_UUID)
initServiceTypeSpinner()
handleClickEvents()
@@ -41,38 +51,43 @@ class ServiceDialog(val listener: ServiceChangeListener, var service: Service =
}
private fun initACTV(actv: AutoCompleteTextView, searchMode: SearchMode) {
- val adapter = Service16BitAdapter(requireContext(), GattUtils.get16BitServices(), searchMode)
+ val adapter =
+ Service16BitAdapter(requireContext(), GattUtils.get16BitServices(), searchMode)
actv.setAdapter(adapter)
actv.setOnItemClickListener { _, _, position, _ ->
val service = adapter.getItem(position)
- actv_service_name.setText(service?.name)
- actv_service_uuid.setText(service?.getIdentifierAsString())
+ binding.actvServiceName.setText(service?.name)
+ binding.actvServiceUuid.setText(service?.getIdentifierAsString())
actv.setSelection(actv.length())
hideKeyboard()
}
}
private fun initServiceTypeSpinner() {
- val adapter = ArrayAdapter(requireContext(), R.layout.spinner_item_layout, resources.getStringArray(R.array.gatt_configurator_service_type))
+ val adapter = ArrayAdapter(
+ requireContext(),
+ R.layout.spinner_item_layout,
+ resources.getStringArray(R.array.gatt_configurator_service_type)
+ )
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item_layout)
- sp_service_type.adapter = adapter
+ binding.spServiceType.adapter = adapter
}
private fun handleClickEvents() {
- btn_bluetooth_gatt_services.setOnClickListener {
+ binding.btnBluetoothGattServices.setOnClickListener {
launchBluetoothGattServicesWebPage()
}
- btn_clear.setOnClickListener {
+ binding.btnClear.setOnClickListener {
resetInput()
}
- btn_cancel.setOnClickListener {
+ binding.btnCancel.setOnClickListener {
dismiss()
}
- btn_save.setOnClickListener {
+ binding.btnSave.setOnClickListener {
setServiceState()
listener.onServiceChanged(service)
dismiss()
@@ -80,16 +95,17 @@ class ServiceDialog(val listener: ServiceChangeListener, var service: Service =
}
private fun setServiceState() {
- if (cb_mandatory_requirements.isChecked) handleMandatoryServiceRequirements()
+
+ if (binding.cbMandatoryRequirements.isChecked) handleMandatoryServiceRequirements()
service.apply {
- name = actv_service_name.text.toString()
- uuid = Uuid(actv_service_uuid.text.toString())
+ name = binding.actvServiceName.text.toString()
+ uuid = Uuid(binding.actvServiceUuid.text.toString())
type = getServiceTypeFromSelection()
}
}
private fun handleMandatoryServiceRequirements() {
- val uuid = UuidUtils.convert16to128UUID(actv_service_uuid.text.toString())
+ val uuid = UuidUtils.convert16to128UUID(binding.actvServiceUuid.text.toString())
service = getMandatoryServiceRequirements(UUID.fromString(uuid))
}
@@ -102,7 +118,8 @@ class ServiceDialog(val listener: ServiceChangeListener, var service: Service =
val characteristicType =
Engine.getCharacteristicByType(characteristicRes.type!!)
val characteristic = Characteristic().apply {
- name = characteristicType?.name ?: getString(R.string.unknown_characteristic_label)
+ name =
+ characteristicType?.name ?: getString(R.string.unknown_characteristic_label)
uuid = characteristicType?.let { charType ->
Uuid(UuidUtils.convert128to16UUID(charType.uuid.toString()))
}
@@ -146,18 +163,18 @@ class ServiceDialog(val listener: ServiceChangeListener, var service: Service =
}
private fun getServiceTypeFromSelection(): Service.Type {
- return when (sp_service_type.selectedItemPosition) {
+ return when (binding.spServiceType.selectedItemPosition) {
0 -> Service.Type.PRIMARY
else -> Service.Type.SECONDARY
}
}
private fun handleNameChanges() {
- actv_service_name.addTextChangedListener(object : TextWatcher {
+ binding.actvServiceName.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- btn_save.isEnabled = isInputValid()
+ binding.btnSave.isEnabled = isInputValid()
setMandatoryRequirementsCheckBoxState()
setServiceTypeSpinnerState()
}
@@ -165,14 +182,16 @@ class ServiceDialog(val listener: ServiceChangeListener, var service: Service =
}
private fun handleUuidChanges() {
- actv_service_uuid.addTextChangedListener(object : TextWatcher {
+ binding.actvServiceUuid.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val len = s?.length
- if ((len == 8 || len == 13 || len == 18 || len == 23) && count > before) actv_service_uuid.append("-")
+ if ((len == 8 || len == 13 || len == 18 || len == 23) && count > before) binding.actvServiceUuid.append(
+ "-"
+ )
- btn_save.isEnabled = isInputValid()
+ binding.btnSave.isEnabled = isInputValid()
setMandatoryRequirementsCheckBoxState()
setServiceTypeSpinnerState()
}
@@ -181,32 +200,34 @@ class ServiceDialog(val listener: ServiceChangeListener, var service: Service =
private fun setMandatoryRequirementsCheckBoxState() {
if (isInput16BitService()) {
- cb_mandatory_requirements.isEnabled = true
+ binding.cbMandatoryRequirements.isEnabled = true
} else {
- cb_mandatory_requirements.isEnabled = false
- cb_mandatory_requirements.isChecked = false
+ binding.cbMandatoryRequirements.isEnabled = false
+ binding.cbMandatoryRequirements.isChecked = false
}
}
private fun setServiceTypeSpinnerState() {
if (isInput16BitService()) {
- sp_service_type.setSelection(0)
- sp_service_type.isEnabled = false
+ binding.spServiceType.setSelection(0)
+ binding.spServiceType.isEnabled = false
} else {
- sp_service_type.isEnabled = true
+ binding.spServiceType.isEnabled = true
}
}
private fun isInput16BitService(): Boolean {
- val name = actv_service_name.text.toString()
- val uuid = actv_service_uuid.text.toString()
+ val name = binding.actvServiceName.text.toString()
+ val uuid = binding.actvServiceUuid.text.toString()
- val result = predefinedServices.filter { it.name == name && it.getIdentifierAsString() == uuid }
+ val result =
+ predefinedServices.filter { it.name == name && it.getIdentifierAsString() == uuid }
return result.isNotEmpty()
}
private fun isInputValid(): Boolean {
- return actv_service_name.text.toString().isNotEmpty() && isUuidValid(actv_service_uuid.text.toString())
+ return binding.actvServiceName.text.toString()
+ .isNotEmpty() && isUuidValid(binding.actvServiceUuid.text.toString())
}
private fun isUuidValid(uuid: String): Boolean {
@@ -214,16 +235,17 @@ class ServiceDialog(val listener: ServiceChangeListener, var service: Service =
}
private fun launchBluetoothGattServicesWebPage() {
- val uriUrl = Uri.parse("https://" + getString(R.string.advertiser_url_bluetooth_gatt_services))
+ val uriUrl =
+ Uri.parse("https://" + getString(R.string.advertiser_url_bluetooth_gatt_services))
val launchBrowser = Intent(Intent.ACTION_VIEW, uriUrl)
startActivity(launchBrowser)
}
private fun resetInput() {
- actv_service_name.setText("")
- actv_service_uuid.setText("")
- cb_mandatory_requirements.isChecked = false
- sp_service_type.setSelection(0)
+ binding.actvServiceName.setText("")
+ binding.actvServiceUuid.setText("")
+ binding.cbMandatoryRequirements.isChecked = false
+ binding.spServiceType.setSelection(0)
}
interface ServiceChangeListener {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/fragments/GattConfiguratorFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/fragments/GattConfiguratorFragment.kt
index 1a65818c..0ec0ca88 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/fragments/GattConfiguratorFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/fragments/GattConfiguratorFragment.kt
@@ -135,6 +135,7 @@ class GattConfiguratorFragment : BaseMainMenuFragment(), OnClickListener {
} else {
fullScreenInfo.root.visibility = View.VISIBLE
rvMainView.visibility = View.GONE
+ restoreHiddenUI()
}
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/AddServiceViewHolder.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/AddServiceViewHolder.kt
index a817eb95..815a7c6f 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/AddServiceViewHolder.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/AddServiceViewHolder.kt
@@ -1,15 +1,19 @@
package com.siliconlabs.bledemo.features.configure.gatt_configurator.viewholders
import android.view.LayoutInflater
-import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
-import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.AdapterAddServiceBinding
import com.siliconlabs.bledemo.features.configure.gatt_configurator.adapters.EditGattServerAdapter.AddServiceListener
-import kotlinx.android.synthetic.main.adapter_add_service.view.*
-class AddServiceViewHolder(view: View, private val addServiceListener: AddServiceListener) : RecyclerView.ViewHolder(view) {
- private val btnAddService = view.btn_add_service
+//import kotlinx.android.synthetic.main.adapter_add_service.view.*
+
+class AddServiceViewHolder(
+ view: AdapterAddServiceBinding,
+ private val addServiceListener: AddServiceListener
+) : RecyclerView.ViewHolder(view.root) {
+ private val btnAddService = view.btnAddService
+
fun bind() {
handleClickEvents()
@@ -22,9 +26,13 @@ class AddServiceViewHolder(view: View, private val addServiceListener: AddServic
}
companion object {
- fun create(parent: ViewGroup, addServiceListener: AddServiceListener): AddServiceViewHolder {
- val view = LayoutInflater.from(parent.context).inflate(R.layout.adapter_add_service, parent, false)
- return AddServiceViewHolder(view, addServiceListener)
+ fun create(
+ parent: ViewGroup,
+ addServiceListener: AddServiceListener
+ ): AddServiceViewHolder {
+ val binding = AdapterAddServiceBinding.inflate(LayoutInflater.from(parent.context))
+
+ return AddServiceViewHolder(binding, addServiceListener)
}
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/EditGattServerViewHolder.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/EditGattServerViewHolder.kt
index d109bc10..96006058 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/EditGattServerViewHolder.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/EditGattServerViewHolder.kt
@@ -1,11 +1,13 @@
package com.siliconlabs.bledemo.features.configure.gatt_configurator.viewholders
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.get
import androidx.recyclerview.widget.RecyclerView
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.AdapterEditGattServerBinding
import com.siliconlabs.bledemo.features.configure.gatt_configurator.activities.GattServerActivity
import com.siliconlabs.bledemo.features.configure.gatt_configurator.adapters.EditGattServerAdapter.ServiceListener
import com.siliconlabs.bledemo.features.configure.gatt_configurator.dialogs.CharacteristicDialog
@@ -13,18 +15,19 @@ import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Chara
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Service
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.removeAsking
import com.siliconlabs.bledemo.features.configure.gatt_configurator.views.GattCharacteristicView
-import kotlinx.android.synthetic.main.adapter_edit_gatt_server.view.*
-
-class EditGattServerViewHolder(view: View, val list: ArrayList, val listener: ServiceListener) : RecyclerView.ViewHolder(view) {
- private val llCharacteristics = view.ll_characteristics
- private val llCharacteristicsOuter = view.ll_characteristics_outer
- private val expandArrow = view.expand_arrow
- private val tvName = view.tv_service_name
- private val tvUuid = view.tv_service_uuid
- private val tvType = view.tv_service_type
- private val ibCopy = view.ib_copy
- private val ibRemove = view.ib_remove
- private val btnAddCharacteristic = view.btn_add_characteristic
+//import kotlinx.android.synthetic.main.adapter_edit_gatt_server.view.*
+
+class EditGattServerViewHolder(view: AdapterEditGattServerBinding, val list: ArrayList, val listener: ServiceListener) :
+ RecyclerView.ViewHolder(view.root) {
+ private val llCharacteristics = view.llCharacteristics
+ private val llCharacteristicsOuter = view.llCharacteristicsOuter
+ private val expandArrow = view.expandArrow
+ private val tvName = view.tvServiceName
+ private val tvUuid = view.tvServiceUuid
+ private val tvType = view.tvServiceType
+ private val ibCopy = view.ibCopy
+ private val ibRemove = view.ibRemove
+ private val btnAddCharacteristic = view.btnAddCharacteristic
fun bind(service: Service) {
llCharacteristics.removeAllViews()
@@ -56,8 +59,8 @@ class EditGattServerViewHolder(view: View, val list: ArrayList, val lis
private fun initCharacteristics(characteristics: ArrayList) {
for (characteristic in characteristics) {
val view = GattCharacteristicView(itemView.context, characteristic)
- handleCharacteristicClickEvents(view, characteristics)
llCharacteristics.addView(view)
+ handleCharacteristicClickEvents(view, characteristics)
}
}
@@ -98,11 +101,25 @@ class EditGattServerViewHolder(view: View, val list: ArrayList, val lis
llCharacteristics.addView(view)
}
- private fun editCharacteristic(characteristic: Characteristic, characteristics: ArrayList) {
+ private fun editCharacteristic(
+ characteristic: Characteristic,
+ characteristics: ArrayList
+ ) {
CharacteristicDialog(object : CharacteristicDialog.CharacteristicChangeListener {
override fun onCharacteristicChanged(characteristic: Characteristic) {
+
val index = characteristics.indexOf(characteristic)
- (llCharacteristics[index] as GattCharacteristicView).refreshView()
+
+ // Get the view at the specified index in the LinearLayout
+ val view = llCharacteristics.getChildAt(index)
+
+ if (view is GattCharacteristicView) {
+ // If the view is a GattCharacteristicView, call refreshView
+ view.refreshView()
+ } else {
+ // Handle the case where the view is not a GattCharacteristicView
+ Log.e("EditCharacteristic", "View at index $index is not a GattCharacteristicView.")
+ }
}
}, characteristic).show((itemView.context as GattServerActivity).supportFragmentManager, "dialog_characteristic")
}
@@ -123,8 +140,9 @@ class EditGattServerViewHolder(view: View, val list: ArrayList, val lis
companion object {
fun create(parent: ViewGroup, list: ArrayList, listener: ServiceListener): EditGattServerViewHolder {
- val view = LayoutInflater.from(parent.context).inflate(R.layout.adapter_edit_gatt_server, parent, false)
- return EditGattServerViewHolder(view, list, listener)
+ val binding = AdapterEditGattServerBinding.inflate(LayoutInflater.from(parent.context))
+
+ return EditGattServerViewHolder(binding, list, listener)
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/GattServerViewHolder.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/GattServerViewHolder.kt
index 98bd95de..1e9652e7 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/GattServerViewHolder.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/viewholders/GattServerViewHolder.kt
@@ -3,6 +3,7 @@ package com.siliconlabs.bledemo.features.configure.gatt_configurator.viewholders
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.LinearLayout
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton
import com.siliconlabs.bledemo.R
@@ -107,7 +108,7 @@ class GattServerViewHolder(
if (service.characteristics.size == 1) R.string.gatt_configurator_one_characteristic
else R.string.gatt_configurator_n_characteristics, service.characteristics.size
)
- ))
+ ).binding.root, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/views/GattCharacteristicView.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/views/GattCharacteristicView.kt
index ab14e305..d84f6e1c 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/views/GattCharacteristicView.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/views/GattCharacteristicView.kt
@@ -3,39 +3,45 @@ package com.siliconlabs.bledemo.features.configure.gatt_configurator.views
import android.content.Context
import android.text.Html
import android.util.AttributeSet
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import androidx.core.view.get
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.ViewGattCharacteristicBinding
import com.siliconlabs.bledemo.features.configure.gatt_configurator.activities.GattServerActivity
import com.siliconlabs.bledemo.features.configure.gatt_configurator.dialogs.DescriptorDialog
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Characteristic
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Descriptor
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Property
import com.siliconlabs.bledemo.features.configure.gatt_configurator.utils.removeAsking
-import kotlinx.android.synthetic.main.view_gatt_characteristic.view.*
+
import com.siliconlabs.bledemo.features.configure.gatt_configurator.views.GattDescriptorView.DescriptorListener
-class GattCharacteristicView(context: Context, attributeSet: AttributeSet? = null) : FrameLayout(context, attributeSet) {
+
+class GattCharacteristicView(context: Context, attributeSet: AttributeSet? = null) :
+ FrameLayout(context, attributeSet) {
private var characteristic: Characteristic? = null
+ lateinit var gattCharacterBinding: ViewGattCharacteristicBinding
constructor(context: Context, characteristic: Characteristic) : this(context) {
this.characteristic = characteristic
+ gattCharacterBinding = ViewGattCharacteristicBinding.inflate(LayoutInflater.from(context),this,true)
initView(characteristic)
handleAddDescriptorClickEvent(characteristic.descriptors)
}
private fun initView(characteristic: Characteristic) {
- tv_characteristic_name.text = characteristic.name
+ gattCharacterBinding.tvCharacteristicName.text = characteristic.name
val uuidHtml = buildString {
append("")
append(context.getString(R.string.UUID_colon_space))
append("")
append(characteristic.uuid?.getAsFormattedText())
}
- tv_characteristic_uuid.text = Html.fromHtml(uuidHtml, Html.FROM_HTML_MODE_LEGACY)
+ gattCharacterBinding.tvCharacteristicUuid.text = Html.fromHtml(uuidHtml, Html.FROM_HTML_MODE_LEGACY)
showSelectedProperties(characteristic)
showOrHideDescriptorsLabelWithDivider()
initDescriptors()
@@ -45,24 +51,28 @@ class GattCharacteristicView(context: Context, attributeSet: AttributeSet? = nul
characteristic?.let {
initView(it)
}
+ gattCharacterBinding.root.invalidate()
}
private fun hideAllProperties() {
- tv_property_read.visibility = View.GONE
- tv_property_write.visibility = View.GONE
- tv_property_indicate.visibility = View.GONE
- tv_property_notify.visibility = View.GONE
+
+ gattCharacterBinding.tvPropertyRead.visibility = View.GONE
+ gattCharacterBinding.tvPropertyWrite.visibility = View.GONE
+ gattCharacterBinding.tvPropertyIndicate.visibility = View.GONE
+ gattCharacterBinding.tvPropertyNotify.visibility = View.GONE
}
private fun showSelectedProperties(characteristic: Characteristic) {
hideAllProperties()
characteristic.properties.apply {
- if (containsKey(Property.READ)) tv_property_read.visibility = View.VISIBLE
- if (containsKey(Property.WRITE)) tv_property_write.visibility = View.VISIBLE
- if (containsKey(Property.WRITE_WITHOUT_RESPONSE)) tv_property_write.visibility = View.VISIBLE
- if (containsKey(Property.RELIABLE_WRITE)) tv_property_write.visibility = View.VISIBLE
- if (containsKey(Property.INDICATE)) tv_property_indicate.visibility = View.VISIBLE
- if (containsKey(Property.NOTIFY)) tv_property_notify.visibility = View.VISIBLE
+ if (containsKey(Property.READ)) gattCharacterBinding.tvPropertyRead.visibility = View.VISIBLE
+ if (containsKey(Property.WRITE)) gattCharacterBinding.tvPropertyWrite.visibility = View.VISIBLE
+ if (containsKey(Property.WRITE_WITHOUT_RESPONSE)) gattCharacterBinding.tvPropertyWrite.visibility =
+ View.VISIBLE
+ if (containsKey(Property.RELIABLE_WRITE)) gattCharacterBinding.tvPropertyWrite.visibility =
+ View.VISIBLE
+ if (containsKey(Property.INDICATE)) gattCharacterBinding.tvPropertyIndicate.visibility = View.VISIBLE
+ if (containsKey(Property.NOTIFY)) gattCharacterBinding.tvPropertyNotify.visibility = View.VISIBLE
}
}
@@ -71,15 +81,18 @@ class GattCharacteristicView(context: Context, attributeSet: AttributeSet? = nul
}
private fun initDescriptors() {
- ll_descriptors.removeAllViews()
+ gattCharacterBinding.llDescriptors.removeAllViews()
for (descriptor in characteristic?.descriptors!!) {
val view = GattDescriptorView(context, descriptor)
handleDescriptorClickEvents(view, characteristic?.descriptors!!)
- ll_descriptors.addView(view)
+ gattCharacterBinding.llDescriptors.addView(view)
}
}
- private fun handleDescriptorClickEvents(view: GattDescriptorView, descriptors: ArrayList) {
+ private fun handleDescriptorClickEvents(
+ view: GattDescriptorView,
+ descriptors: ArrayList
+ ) {
view.setDescriptorListener(object : DescriptorListener {
override fun onCopyDescriptor(descriptor: Descriptor) {
copyDescriptor(descriptor, descriptors)
@@ -98,7 +111,8 @@ class GattCharacteristicView(context: Context, attributeSet: AttributeSet? = nul
}
private fun handleAddDescriptorClickEvent(descriptors: ArrayList) {
- btn_add_descriptor.setOnClickListener {
+
+ gattCharacterBinding.btnAddDescriptor.setOnClickListener {
DescriptorDialog(object : DescriptorDialog.DescriptorChangeListener {
override fun onDescriptorChanged(descriptor: Descriptor) {
addDescriptor(descriptor, descriptors)
@@ -112,7 +126,7 @@ class GattCharacteristicView(context: Context, attributeSet: AttributeSet? = nul
handleDescriptorClickEvents(view, descriptors)
descriptors.add(descriptor)
- ll_descriptors.addView(view)
+ gattCharacterBinding.llDescriptors.addView(view)
showOrHideDescriptorsLabelWithDivider()
}
@@ -122,21 +136,32 @@ class GattCharacteristicView(context: Context, attributeSet: AttributeSet? = nul
descriptors.add(copiedDescriptor)
handleDescriptorClickEvents(view, descriptors)
- ll_descriptors.addView(view)
+ gattCharacterBinding.llDescriptors.addView(view)
}
- private fun editDescriptor(descriptor: Descriptor, descriptors: ArrayList) {
+ private fun editDescriptor(
+ descriptor: Descriptor,
+ descriptors: ArrayList) {
DescriptorDialog(object : DescriptorDialog.DescriptorChangeListener {
override fun onDescriptorChanged(descriptor: Descriptor) {
val index = descriptors.indexOf(descriptor)
- (ll_descriptors[index] as GattDescriptorView).refreshView()
+ val view = gattCharacterBinding.llDescriptors.getChildAt(index)
+ if(view is GattDescriptorView){
+ view.refreshView()
+ }else{
+ Log.e("EditDescriptor", "View at index $index is not a GattDescriptorView.")
+ }
+
}
- }, descriptor).show((context as GattServerActivity).supportFragmentManager, "dialog_descriptor")
+ }, descriptor).show(
+ (context as GattServerActivity).supportFragmentManager,
+ "dialog_descriptor"
+ )
}
private fun removeDescriptor(descriptor: Descriptor, descriptors: ArrayList) {
val index = descriptors.indexOf(descriptor)
- ll_descriptors.removeViewAt(index)
+ gattCharacterBinding.llDescriptors.removeViewAt(index)
descriptors.remove(descriptor)
showOrHideDescriptorsLabelWithDivider()
@@ -144,23 +169,24 @@ class GattCharacteristicView(context: Context, attributeSet: AttributeSet? = nul
private fun showOrHideDescriptorsLabelWithDivider() {
characteristic?.descriptors?.apply {
- tv_descriptors.visibility = if (isEmpty()) View.GONE else View.VISIBLE
- cv_descriptors.visibility = if (isEmpty()) View.GONE else View.VISIBLE
+
+ gattCharacterBinding.tvDescriptors.visibility = if (isEmpty()) View.GONE else View.VISIBLE
+ gattCharacterBinding.cvDescriptors.visibility = if (isEmpty()) View.GONE else View.VISIBLE
}
}
fun setCharacteristicListener(listener: CharacteristicListener) {
- ib_copy.setOnClickListener {
+ gattCharacterBinding.ibCopy.setOnClickListener {
characteristic?.let {
listener.onCopyCharacteristic(it)
}
}
- ib_edit.setOnClickListener {
+ gattCharacterBinding.ibEdit.setOnClickListener {
characteristic?.let {
listener.onEditCharacteristic(it)
}
}
- ib_remove.setOnClickListener {
+ gattCharacterBinding.ibRemove.setOnClickListener {
characteristic?.let {
listener.onRemoveCharacteristic(it)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/views/GattDescriptorView.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/views/GattDescriptorView.kt
index 10fd70e5..a9bc5576 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/views/GattDescriptorView.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/gatt_configurator/views/GattDescriptorView.kt
@@ -8,33 +8,44 @@ import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.ViewGattDescriptorBinding
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Descriptor
import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Property
-import kotlinx.android.synthetic.main.view_gatt_descriptor.view.*
-import kotlinx.android.synthetic.main.view_gatt_descriptor.view.ib_copy
-import kotlinx.android.synthetic.main.view_gatt_descriptor.view.ib_edit
-import kotlinx.android.synthetic.main.view_gatt_descriptor.view.ib_remove
-import kotlinx.android.synthetic.main.view_gatt_descriptor.view.tv_property_read
-import kotlinx.android.synthetic.main.view_gatt_descriptor.view.tv_property_write
-
-class GattDescriptorView(context: Context, attributeSet: AttributeSet? = null) : FrameLayout(context, attributeSet) {
+
+//import kotlinx.android.synthetic.main.view_gatt_descriptor.view.*
+//import kotlinx.android.synthetic.main.view_gatt_descriptor.view.ib_copy
+//import kotlinx.android.synthetic.main.view_gatt_descriptor.view.ib_edit
+//import kotlinx.android.synthetic.main.view_gatt_descriptor.view.ib_remove
+//import kotlinx.android.synthetic.main.view_gatt_descriptor.view.tv_property_read
+//import kotlinx.android.synthetic.main.view_gatt_descriptor.view.tv_property_write
+
+class GattDescriptorView(context: Context, attributeSet: AttributeSet? = null) :
+ FrameLayout(context, attributeSet) {
private var descriptor: Descriptor? = null
+ lateinit var gattViewDescriptorBinding: ViewGattDescriptorBinding
constructor(context: Context, descriptor: Descriptor) : this(context) {
this.descriptor = descriptor
initView(descriptor)
- if(descriptor.isPredefined) hideButtons()
+ if (descriptor.isPredefined) hideButtons()
}
init {
- LayoutInflater.from(context).inflate(R.layout.view_gatt_descriptor, this, true)
+ gattViewDescriptorBinding = ViewGattDescriptorBinding.inflate(LayoutInflater.from(context),this,true)
}
private fun initView(descriptor: Descriptor) {
- tv_descriptor_name.text = descriptor.name
- tv_descriptor_uuid.text = buildBoldHeaderTextLine(context.getString(R.string.UUID_colon_space), descriptor.uuid?.getAsFormattedText())
- tv_descriptor_value.text = buildBoldHeaderTextLine(context.getString(R.string.value_colon_space), descriptor.value?.getAsFormattedText())
+
+ gattViewDescriptorBinding.tvDescriptorName.text = descriptor.name
+ gattViewDescriptorBinding.tvDescriptorUuid.text = buildBoldHeaderTextLine(
+ context.getString(R.string.UUID_colon_space),
+ descriptor.uuid?.getAsFormattedText()
+ )
+ gattViewDescriptorBinding.tvDescriptorValue.text = buildBoldHeaderTextLine(
+ context.getString(R.string.value_colon_space),
+ descriptor.value?.getAsFormattedText()
+ )
showSelectedProperties(descriptor)
}
@@ -52,39 +63,42 @@ class GattDescriptorView(context: Context, attributeSet: AttributeSet? = null) :
descriptor?.let {
initView(it)
}
+ gattViewDescriptorBinding.root.invalidate()
}
-
private fun hideButtons() {
- ib_copy.visibility = View.GONE
- ib_remove.visibility = View.GONE
- ib_edit.visibility = View.GONE
+
+ gattViewDescriptorBinding.ibCopy.visibility = View.GONE
+ gattViewDescriptorBinding.ibRemove.visibility = View.GONE
+ gattViewDescriptorBinding.ibEdit.visibility = View.GONE
}
private fun hideAllProperties() {
- tv_property_read.visibility = View.GONE
- tv_property_write.visibility = View.GONE
+ gattViewDescriptorBinding.tvPropertyRead.visibility = View.GONE
+
+ gattViewDescriptorBinding.tvPropertyWrite.visibility = View.GONE
}
private fun showSelectedProperties(descriptor: Descriptor) {
hideAllProperties()
descriptor.properties.apply {
- if (containsKey(Property.READ)) tv_property_read.visibility = View.VISIBLE
- if (containsKey(Property.WRITE)) tv_property_write.visibility = View.VISIBLE
+ gattViewDescriptorBinding.tvPropertyRead
+ if (containsKey(Property.READ)) gattViewDescriptorBinding.tvPropertyRead.visibility = View.VISIBLE
+ if (containsKey(Property.WRITE)) gattViewDescriptorBinding.tvPropertyWrite.visibility = View.VISIBLE
}
}
fun setDescriptorListener(listener: DescriptorListener) {
- ib_copy.setOnClickListener {
+ gattViewDescriptorBinding.ibCopy.setOnClickListener {
descriptor?.let {
listener.onCopyDescriptor(it)
}
}
- ib_edit.setOnClickListener {
+ gattViewDescriptorBinding.ibEdit.setOnClickListener {
descriptor?.let {
listener.onEditDescriptor(it)
}
}
- ib_remove.setOnClickListener {
+ gattViewDescriptorBinding.ibRemove.setOnClickListener {
descriptor?.let {
listener.onRemoveDescriptor(it)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/blinky/fragments/BlinkyFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/blinky/fragments/BlinkyFragment.kt
index 39b1ea9e..a3609a64 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/blinky/fragments/BlinkyFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/blinky/fragments/BlinkyFragment.kt
@@ -5,13 +5,18 @@ import android.view.View
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
+import by.kirich1409.viewbindingdelegate.viewBinding
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.FragmentBlinkyBinding
import com.siliconlabs.bledemo.features.demo.blinky.models.LightState
import com.siliconlabs.bledemo.features.demo.blinky.viewmodels.BlinkyViewModel
-import kotlinx.android.synthetic.main.fragment_blinky.*
+
+//import kotlinx.android.synthetic.main.fragment_blinky.*
class BlinkyFragment : Fragment(R.layout.fragment_blinky) {
private lateinit var viewModel: BlinkyViewModel
+ private val layout by viewBinding(FragmentBlinkyBinding::bind)
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -35,23 +40,24 @@ class BlinkyFragment : Fragment(R.layout.fragment_blinky) {
}
private fun switchLightOn() {
- iv_light_bulb.setImageResource(R.drawable.light_on)
+ layout.ivLightBulb.setImageResource(R.drawable.light_on)
}
private fun switchLightOff() {
- iv_light_bulb.setImageResource(R.drawable.light_off)
+ layout.ivLightBulb.setImageResource(R.drawable.light_off)
}
private fun setButtonImage(isPressed: Boolean) {
+
if (isPressed) {
- iv_button.setImageResource(R.drawable.ic_button_on)
+ layout.ivButton.setImageResource(R.drawable.ic_button_on)
} else {
- iv_button.setImageResource(R.drawable.ic_button_off)
+ layout.ivButton.setImageResource(R.drawable.ic_button_off)
}
}
private fun handleClickEvents() {
- iv_light_bulb.setOnClickListener {
+ layout.ivLightBulb.setOnClickListener {
viewModel.changeLightState()
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/connected_lighting/fragments/ConnectedLightingFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/connected_lighting/fragments/ConnectedLightingFragment.kt
index 88d83a8d..9ab8edd8 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/connected_lighting/fragments/ConnectedLightingFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/connected_lighting/fragments/ConnectedLightingFragment.kt
@@ -11,20 +11,28 @@ import com.siliconlabs.bledemo.features.demo.connected_lighting.activities.Conne
import com.siliconlabs.bledemo.features.demo.connected_lighting.presenters.ConnectedLightingPresenter
import com.siliconlabs.bledemo.features.demo.connected_lighting.models.TriggerSource
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.fragment_light.*
+import com.siliconlabs.bledemo.databinding.FragmentLightBinding
+
+//import kotlinx.android.synthetic.main.fragment_light.*
class ConnectedLightingFragment : Fragment(), ConnectedLightingPresenter.View {
lateinit var presenter: ConnectedLightingPresenter
+ private lateinit var binding: FragmentLightBinding
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.fragment_light, container, false)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentLightBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter = ConnectedLightingPresenter(this, activity as ConnectedLightingActivity)
- btn_lightbulb.setOnClickListener {
+ binding.btnLightbulb.setOnClickListener {
view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
presenter.onLightClicked()
}
@@ -32,40 +40,43 @@ class ConnectedLightingFragment : Fragment(), ConnectedLightingPresenter.View {
override fun showLightState(lightOn: Boolean) {
if (lightOn) {
- btn_lightbulb.setImageResource(R.drawable.light_on)
- tv_light_status.setText(R.string.light_demo_on)
+ binding.btnLightbulb.setImageResource(R.drawable.light_on)
+ binding.tvLightStatus.setText(R.string.light_demo_on)
} else {
- btn_lightbulb.setImageResource(R.drawable.light_off)
- tv_light_status.setText(R.string.light_demo_off)
+ binding.btnLightbulb.setImageResource(R.drawable.light_off)
+ binding.tvLightStatus.setText(R.string.light_demo_off)
}
}
override fun showTriggerSourceDetails(source: TriggerSource?) {
+
if (isAdded && !isDetached && !isRemoving) {
- if(source?.iconId == android.R.color.transparent) {
- iv_light_change_source_logo.visibility = View.GONE
+ if (source?.iconId == android.R.color.transparent) {
+ binding.ivLightChangeSourceLogo.visibility = View.GONE
} else {
- iv_light_change_source_logo.setImageResource(source?.iconId!!)
- iv_light_change_source_logo.visibility = View.VISIBLE
+ binding.ivLightChangeSourceLogo.setImageResource(source?.iconId!!)
+ binding.ivLightChangeSourceLogo.visibility = View.VISIBLE
}
- tv_light_change_source_name.text = getText(source.textResId)
+
+ binding.tvLightChangeSourceName.text = getText(source.textResId)
}
}
override fun showTriggerSourceAddress(sourceAddress: String, source: TriggerSource?) {
+ binding.tvLightChangeSource
if (TriggerSource.UNKNOWN == source) {
- tv_light_change_source.text = getString(R.string.light_demo_changed_source_unknown)
+ binding.tvLightChangeSource.text = getString(R.string.light_demo_changed_source_unknown)
} else {
- tv_light_change_source.text = StringBuffer(sourceAddress).reverse().toString()
+ binding.tvLightChangeSource.text = StringBuffer(sourceAddress).reverse().toString()
}
}
override fun showDeviceDisconnectedDialog() {
- AlertDialog.Builder(activity!!)
- .setMessage(R.string.light_demo_connection_lost)
- .setPositiveButton(R.string.light_demo_connection_lost_button) { dialog, which -> dialog.dismiss() }
- .setOnDismissListener { presenter.leaveDemo() }
- .create()
- .show()
+ AlertDialog.Builder(requireActivity())
+ .setMessage(R.string.light_demo_connection_lost)
+ .setPositiveButton(R.string.light_demo_connection_lost_button) { dialog, which -> dialog.dismiss() }
+ .setOnDismissListener { presenter.leaveDemo() }
+ .create()
+ .show()
}
}
\ 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
index 2b07a9af..c39947b2 100644
--- 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
@@ -1,10 +1,15 @@
package com.siliconlabs.bledemo.features.demo.devkitsensor917.activities
import android.annotation.SuppressLint
+import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.os.Build
import android.os.Bundle
import android.view.MenuItem
+import android.view.View
import android.widget.Toast
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
@@ -14,10 +19,10 @@ import androidx.fragment.app.Fragment
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.databinding.Activity917DevKitSensorLayoutBinding
import com.siliconlabs.bledemo.features.demo.devkitsensor917.APIInterface
-import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.ScanResponse
import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.SensorsResponse
import com.siliconlabs.bledemo.features.demo.devkitsensor917.utils.DevKitSensorChecker
import com.siliconlabs.bledemo.features.demo.devkitsensor917.utils.DevKitSensorControl
+import com.siliconlabs.bledemo.features.demo.devkitsensor917.utils.DevKitSensorSharedData
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@@ -49,13 +54,23 @@ class DevKitSensor917Activity : AppCompatActivity() {
actionBar!!.setHomeAsUpIndicator(R.drawable.matter_back)
actionBar.setDisplayHomeAsUpEnabled(true)
val ipAddress = intent.getStringExtra(IP_ADDRESS)
- if (ipAddress != null) {
- showProgressDialog(this.getString(R.string.dev_kit_progress_bar_message))
- println("IP ADDRESS Imported: $ipAddress")
- initGrid(ipAddress)
- GlobalScope.launch {
- doInSensorBackground(ipAddress)
+ if (isNetworkAvailable(this)) {
+ if (ipAddress != null) {
+ binding.envGridPlace.visibility = View.VISIBLE
+ binding.envGrid.visibility = View.VISIBLE
+ binding.placeholder.visibility = View.GONE
+ showProgressDialog(this.getString(R.string.dev_kit_progress_bar_message))
+ println("IP ADDRESS Imported: $ipAddress")
+ initGrid(ipAddress)
+ GlobalScope.launch {
+ doInSensorBackground(ipAddress)
+ }
}
+ } else {
+ binding.envGridPlace.visibility = View.GONE
+ binding.envGrid.visibility = View.GONE
+ binding.placeholder.visibility = View.VISIBLE
+ Toast.makeText(this, "Please turn the WiFi Setting", Toast.LENGTH_SHORT).show()
}
}
@@ -84,7 +99,7 @@ class DevKitSensor917Activity : AppCompatActivity() {
removeProgress()
runOnUiThread {
Toast.makeText(
- baseContext,
+ baseContext,
"API All Sensors Response failed",
Toast.LENGTH_SHORT
).show()
@@ -120,9 +135,8 @@ class DevKitSensor917Activity : AppCompatActivity() {
getString(getTileDescription(it.key)),
ContextCompat.getDrawable(this.context, getTileIcon(it.key))
).also {
-
- addView(it)
- it.setListener(it.tag, ipAddress)
+ addView(it.sensorDemoGridItemBinding.root)
+ it.setListener(DevKitSensorSharedData.sensorDescription.toString(), ipAddress)
}
@@ -179,6 +193,29 @@ class DevKitSensor917Activity : AppCompatActivity() {
}
+ private fun isNetworkAvailable(context: Context?): Boolean {
+ if (context == null) return false
+ val connectivityManager =
+ context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ val capabilities =
+ connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
+ if (capabilities != null) {
+ when {
+ capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
+ return true
+ }
+ }
+ }
+ } else {
+ val activeNetworkInfo = connectivityManager.activeNetworkInfo
+ if (activeNetworkInfo != null && activeNetworkInfo.isConnected) {
+ return true
+ }
+ }
+ return false
+ }
+
interface ResponseListener {
fun fetchData(response: SensorsResponse?)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/sensorsResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/sensorsResponse.kt
index 6be5cf5f..44c0eecb 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/sensorsResponse.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/sensorsResponse.kt
@@ -1,5 +1,6 @@
package com.siliconlabs.bledemo.features.demo.devkitsensor917.model
+
data class SensorsResponse(
val led: LEDResponse,
val light: AmbientLightResponse,
@@ -8,4 +9,4 @@ data class SensorsResponse(
val gyroscope: AccelerometerGyroScopeResponse,
val humidity: HumidityResponse,
val microphone: MicrophoneResponse
-)
+)
\ 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
index 575d4f49..f48bfee1 100644
--- 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
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.graphics.drawable.Drawable
+import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
@@ -14,17 +15,13 @@ import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.gridlayout.widget.GridLayout
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.SensorDemoGridItemBinding
import com.siliconlabs.bledemo.features.demo.devkitsensor917.APIInterface
import com.siliconlabs.bledemo.features.demo.devkitsensor917.activities.DevKitSensor917Activity
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.SensorsResponse
-import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.TempResponse
-import kotlinx.android.synthetic.main.environmentdemo_tile.view.env_description
-import kotlinx.android.synthetic.main.environmentdemo_tile.view.env_icon
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -62,18 +59,19 @@ open class DevKitSensorControl(
constructor(context: Context) : this(context, null, null)
- private val tileView: View = inflate(context, R.layout.sensor_demo_grid_item, this)
+ var sensorDemoGridItemBinding: SensorDemoGridItemBinding =
+ SensorDemoGridItemBinding.inflate(LayoutInflater.from(context))
fun setListener(tag: Any, ipAddress: String) {
val code = tag.toString()
- tileView.setOnClickListener {
+ sensorDemoGridItemBinding.cardviewEnvTile.setOnClickListener {
when (code) {
- temperature -> showTemperatureDialog(code, ipAddress)
- humidity -> showHumidityDialog(code, ipAddress)
- ambientLight -> showAmbientLightDialog(code, ipAddress)
- microphone -> showMicrophoneDialog(code, ipAddress)
+ TEMPERATURE -> showTemperatureDialog(code, ipAddress)
+ HUMIDITY -> showHumidityDialog(code, ipAddress)
+ AMBIENT_LIGHT -> showAmbientLightDialog(code, ipAddress)
+ MICROPHONE -> showMicrophoneDialog(code, ipAddress)
LED -> showLEDControlDialog(code, ipAddress)
- motion -> showMotionDialog(code, ipAddress)
+ MOTION -> showMotionDialog(code, ipAddress)
}
}
}
@@ -88,12 +86,12 @@ open class DevKitSensorControl(
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 header: TextView = devkitSensorDialog.findViewById(R.id.header)
+ val yesBtn: TextView = devkitSensorDialog.findViewById(R.id.yes_opt)
+ val noBtn: TextView = devkitSensorDialog.findViewById(R.id.no_opt)
+ val orientationX: TextView = devkitSensorDialog.findViewById(R.id.orient_x)
+ val orientationY: TextView = devkitSensorDialog.findViewById(R.id.orientation_y)
+ val orientationZ: TextView = devkitSensorDialog.findViewById(R.id.orientation_z)
val degreeString = context.getString(R.string.motion_orientation_degree)
if (gyroResponse != null && gyroResponse!!.x.isNotEmpty()) {
orientationX.text = String.format(degreeString, gyroResponse!!.x.toFloat())
@@ -112,9 +110,9 @@ open class DevKitSensorControl(
}
val accelerationString = context.getString(R.string.motion_acceleration_g)
- 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
+ val acceloX: TextView = devkitSensorDialog.findViewById(R.id.accelo_x)
+ val acceloY: TextView = devkitSensorDialog.findViewById(R.id.accelo_y)
+ val acceloZ: TextView = devkitSensorDialog.findViewById(R.id.accelo_z)
if (acceloResponse != null && acceloResponse!!.x.isNotEmpty()) {
acceloX.text = String.format(accelerationString, acceloResponse!!.x.toFloat())
} else {
@@ -151,7 +149,7 @@ open class DevKitSensorControl(
apiJob?.cancel()
}
}
- header.text = title + space + context.getString(R.string.title_sensor)
+ header.text = title + SPACE + context.getString(R.string.title_sensor)
devkitSensorDialog.show()
apiJob = CoroutineScope(Dispatchers.IO).launch {
while (true) {
@@ -259,19 +257,19 @@ open class DevKitSensorControl(
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 dataHolder = devKitSensorDialog.findViewById(R.id.txt_value) as TextView
+ val header: TextView = devKitSensorDialog.findViewById(R.id.header)
+ val subTitle: TextView = devKitSensorDialog.findViewById(R.id.subTitle)
+ val yesBtn: TextView = devKitSensorDialog.findViewById(R.id.yes_opt)
+ val noBtn: TextView = devKitSensorDialog.findViewById(R.id.no_opt)
+ val image: ImageView = devKitSensorDialog.findViewById(R.id.image)
+ val dataHolder: TextView = devKitSensorDialog.findViewById(R.id.txt_value)
dataHolder.text = context.getString(R.string.matter_init_value)
// println("tempResponse :${tempResponse!!.temperature_celcius}")
if (tempResponse != null && tempResponse!!.isNotEmpty()) {
- dataHolder.text = tempResponse + " ℃"
+ dataHolder.text = "$tempResponse ℃"
}
image.setImageResource(R.drawable.icon_temp)
- header.text = title + space + context.getString(R.string.title_sensor)
+ header.text = title + SPACE + context.getString(R.string.title_sensor)
subTitle.text = title
yesBtn.setOnClickListener {
yesBtn.isEnabled = false
@@ -436,17 +434,19 @@ open class DevKitSensorControl(
}
init {
- tileView.setTag(description)
- tileView.apply {
- env_description.text = description
- env_icon.setImageDrawable(icon)
+ DevKitSensorSharedData.sensorDescription = description
+ sensorDemoGridItemBinding.cardviewEnvTile.apply {
+ sensorDemoGridItemBinding.envDescription.text = description
+ sensorDemoGridItemBinding.envIcon.setImageDrawable(icon)
}
+
layoutParams = GridLayout.LayoutParams(
GridLayout.spec(GridLayout.UNDEFINED, 1f),
GridLayout.spec(GridLayout.UNDEFINED, 1f)
).apply {
width = 0
}
+
}
@SuppressLint("SetTextI18n")
@@ -458,15 +458,15 @@ open class DevKitSensorControl(
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 header: TextView = devKitSensorDialog.findViewById(R.id.header)
+ val subTitle: TextView = devKitSensorDialog.findViewById(R.id.subTitle)
+ val yesBtn: TextView = devKitSensorDialog.findViewById(R.id.yes_opt)
+ val noBtn: TextView = devKitSensorDialog.findViewById(R.id.no_opt)
+ val image: ImageView = devKitSensorDialog.findViewById(R.id.image)
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)
+ header.text = title + SPACE + context.getString(R.string.title_sensor)
subTitle.text = title
yesBtn.setOnClickListener {
CoroutineScope(Dispatchers.IO).launch {
@@ -499,20 +499,20 @@ open class DevKitSensorControl(
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
+ val header: TextView = devKitSensorDialog.findViewById(R.id.header)
+ val subTitle: TextView = devKitSensorDialog.findViewById(R.id.subTitle)
+ val yesBtn: TextView = devKitSensorDialog.findViewById(R.id.yes_opt)
+ val noBtn: TextView = devKitSensorDialog.findViewById(R.id.no_opt)
+ val image: ImageView = devKitSensorDialog.findViewById(R.id.image)
+ val abiHolder: TextView = devKitSensorDialog.findViewById(R.id.txt_value)
abiHolder.text = context.getString(R.string.dev_kit_sensor_ambient_init_value)
if (ambiResponse != null && ambiResponse!!.isNotEmpty()) {
- abiHolder.text = ambiResponse + " lx"
+ abiHolder.text = "$ambiResponse lx"
}
abiHolder.textSize = 50F
image.setImageResource(R.drawable.icon_light)
- header.text = title + space + context.getString(R.string.title_sensor)
+ header.text = title + SPACE + context.getString(R.string.title_sensor)
subTitle.text = title
yesBtn.setOnClickListener {
@@ -579,18 +579,18 @@ open class DevKitSensorControl(
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)
+ val header: TextView = devKitSensorDialog.findViewById(R.id.header)
+ val subTitle: TextView = devKitSensorDialog.findViewById(R.id.subTitle)
+ val yesBtn: TextView = devKitSensorDialog.findViewById(R.id.yes_opt)
+ val noBtn: TextView = devKitSensorDialog.findViewById(R.id.no_opt)
+ onLEDBtn = devKitSensorDialog.findViewById(R.id.onButton)!!
+ offLEDBtn = devKitSensorDialog.findViewById(R.id.offButton)!!
+ redLEDBtn = devKitSensorDialog.findViewById(R.id.redButton)!!
+ greenLEDBtn = devKitSensorDialog.findViewById(R.id.greenButton)!!
+ blueLEDBtn = devKitSensorDialog.findViewById(R.id.blueButton)!!
+ ledImageStatus = devKitSensorDialog.findViewById(R.id.imageLight)!!
+
+ header.text = title + SPACE + context.getString(R.string.title_control)
subTitle.text = title
subTitle.visibility = View.GONE
@@ -687,8 +687,7 @@ open class DevKitSensorControl(
if (btnBlueStatus) {
onLEDBtn.setBackgroundResource(R.drawable.button_background_soft_black_box)
blueLEDBtn.setBackgroundResource(R.drawable.button_background_blue_box)
- } else {
- offLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box)
+ }else{
blueLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box)
}
if (btnRedStatus && btnGreenStatus && btnBlueStatus) {
@@ -740,7 +739,7 @@ open class DevKitSensorControl(
val retro = Retrofit.Builder().baseUrl(url)
.addConverterFactory(GsonConverterFactory.create()).build()
val ledStatus = retro.create(APIInterface::class.java)
- val params: MutableMap = HashMap()
+ val params: MutableMap = HashMap()
var statusRed: String = OFF
if (red) {
statusRed = ON
@@ -775,7 +774,7 @@ open class DevKitSensorControl(
setBtnColorBackground()
}
} else {
-
+ //ignore
}
}
@@ -902,7 +901,7 @@ open class DevKitSensorControl(
btnBlueStatus = false
btnGreenStatus = false
setOffBtnBackground()
- imageForLightOn(view, false, false, false)
+ imageForLightOn(view, btnRedStatus, btnBlueStatus, btnGreenStatus)
Toast.makeText(
context,
"Failed to connect. Check your Wi-Fi connection",
@@ -1024,18 +1023,18 @@ open class DevKitSensorControl(
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
+ val header: TextView = devKitSensorDialog.findViewById(R.id.header)
+ val subTitle: TextView = devKitSensorDialog.findViewById(R.id.subTitle)
+ val yesBtn: TextView = devKitSensorDialog.findViewById(R.id.yes_opt)
+ val noBtn: TextView = devKitSensorDialog.findViewById(R.id.no_opt)
+ val image: ImageView = devKitSensorDialog.findViewById(R.id.image)
+ val humidityHolder: TextView = devKitSensorDialog.findViewById(R.id.txt_value)
humidityHolder.text = context.getString(R.string.dev_kit_sensor_humidity_init_value)
if (humiResponse != null && humiResponse!!.isNotEmpty()) {
- humidityHolder.text = humiResponse + " %"
+ humidityHolder.text = "$humiResponse %"
}
image.setImageResource(R.drawable.icon_environment)
- header.text = title + space + context.getString(R.string.title_sensor)
+ header.text = title + SPACE + context.getString(R.string.title_sensor)
subTitle.text = title
yesBtn.setOnClickListener {
yesBtn.isEnabled = false
@@ -1063,36 +1062,31 @@ open class DevKitSensorControl(
override fun fetchData(response: SensorsResponse?) {
- //temperatureResponse = tempResponse
- println("----------------${response!!.led.blue}")
if (response != null) {
//Temp
- if (response.temperature != null && response.temperature.temperature_celcius.isNotEmpty()) {
- println("----------------${response.temperature.temperature_celcius}")
+ if (response.temperature.temperature_celcius.isNotEmpty()) {
tempResponse = response.temperature.temperature_celcius
}
//Humi
- if (response.humidity != null && response.humidity.humidity_percentage.isNotEmpty()) {
- println("----------------${response.humidity.humidity_percentage}")
+ if (response.humidity.humidity_percentage.isNotEmpty()) {
humiResponse = response.temperature.temperature_celcius
}
//Ambi
- if (response.light != null && response.light.ambient_light_lux.isNotEmpty()) {
- println("----------------${response.light.ambient_light_lux}")
+ if (response.light.ambient_light_lux.isNotEmpty()) {
ambiResponse = response.light.ambient_light_lux
}
}
-
}
+
companion object {
- const val space = " "
- const val temperature = "Temperature"
- const val humidity = "Humidity"
- const val ambientLight = "Ambient Light"
- const val microphone = "Microphone"
+ const val SPACE = " "
+ const val TEMPERATURE = "Temperature"
+ const val HUMIDITY = "Humidity"
+ const val AMBIENT_LIGHT = "Ambient Light"
+ const val MICROPHONE = "Microphone"
const val LED = "LED"
- const val motion = "Motion"
+ const val MOTION = "Motion"
const val TIME_OUT = 2000L
const val OFF = "off"
const val ON = "on"
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorSharedData.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorSharedData.kt
new file mode 100644
index 00000000..2a4f6c6a
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorSharedData.kt
@@ -0,0 +1,5 @@
+package com.siliconlabs.bledemo.features.demo.devkitsensor917.utils
+
+object DevKitSensorSharedData {
+ var sensorDescription: String? = null
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/health_thermometer/activities/HealthThermometerActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/health_thermometer/activities/HealthThermometerActivity.kt
index 2d3ed058..0ceff7ed 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/health_thermometer/activities/HealthThermometerActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/health_thermometer/activities/HealthThermometerActivity.kt
@@ -7,6 +7,8 @@ import android.content.Intent
import android.graphics.Typeface
import android.os.Bundle
import android.text.TextUtils
+import android.view.LayoutInflater
+import android.widget.TextView
import com.siliconlabs.bledemo.home_screen.dialogs.SelectDeviceDialog
import com.siliconlabs.bledemo.bluetooth.ble.GattCharacteristic
import com.siliconlabs.bledemo.bluetooth.ble.GattService
@@ -15,9 +17,11 @@ import com.siliconlabs.bledemo.features.demo.health_thermometer.models.Temperatu
import com.siliconlabs.bledemo.features.demo.health_thermometer.models.TemperatureReading.HtmType
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.activities.BaseDemoActivity
+import com.siliconlabs.bledemo.databinding.ActivityThermometerBinding
import com.siliconlabs.bledemo.utils.BLEUtils.setNotificationForCharacteristic
import com.siliconlabs.bledemo.utils.Notifications
-import kotlinx.android.synthetic.main.activity_thermometer.*
+
+//import kotlinx.android.synthetic.main.activity_thermometer.*
@SuppressLint("MissingPermission")
class HealthThermometerActivity : BaseDemoActivity() {
@@ -26,6 +30,7 @@ class HealthThermometerActivity : BaseDemoActivity() {
private var currentReading: TemperatureReading? = null
private var currentType: TemperatureReading.Type? = null
+ private lateinit var binding: ActivityThermometerBinding
private val gattCallback: TimeoutGattCallback = object : TimeoutGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
@@ -53,13 +58,18 @@ class HealthThermometerActivity : BaseDemoActivity() {
}
}
if (startNotificationForCharacteristicFromHere) {
- setNotificationForCharacteristic(gatt, GattService.HealthThermometer,
- GattCharacteristic.Temperature,
- Notifications.INDICATE)
+ setNotificationForCharacteristic(
+ gatt, GattService.HealthThermometer,
+ GattCharacteristic.Temperature,
+ Notifications.INDICATE
+ )
}
}
- override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic
+ ) {
super.onCharacteristicChanged(gatt, characteristic)
if (GattCharacteristic.fromUuid(characteristic.uuid) == GattCharacteristic.Temperature) {
val reading = TemperatureReading.fromCharacteristic(characteristic)
@@ -70,40 +80,56 @@ class HealthThermometerActivity : BaseDemoActivity() {
}
runOnUiThread {
setCurrentReading(reading)
- connection_bar_text.text = getString(R.string.demo_connected_to, deviceName)
+ binding.connectionBarText.text =
+ getString(R.string.demo_connected_to, deviceName)
}
}
}
- override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic,
+ status: Int
+ ) {
super.onCharacteristicRead(gatt, characteristic, status)
if (GattCharacteristic.fromUuid(characteristic.uuid) == GattCharacteristic.TemperatureType) {
- htmType = HtmType.values()[characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0)]
- setNotificationForCharacteristic(gatt, GattService.HealthThermometer,
- GattCharacteristic.Temperature,
- Notifications.INDICATE)
+ htmType = HtmType.values()[characteristic.getIntValue(
+ BluetoothGattCharacteristic.FORMAT_UINT8,
+ 0
+ )]
+ setNotificationForCharacteristic(
+ gatt, GattService.HealthThermometer,
+ GattCharacteristic.Temperature,
+ Notifications.INDICATE
+ )
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_thermometer)
+ binding = ActivityThermometerBinding.inflate(LayoutInflater.from(this))
+ setContentView(binding.root)
+ //setContentView(R.layout.activity_thermometer)
- thermo_large_temperature.setFontFamily("sans-serif-thin", Typeface.NORMAL)
- type_switch.setOnCheckedChangeListener { _, isChecked -> onTabClick(isChecked) }
+ binding.thermoLargeTemperature.setFontFamily("sans-serif-thin", Typeface.NORMAL)
+ binding.typeSwitch.setOnCheckedChangeListener { _, isChecked -> onTabClick(isChecked) }
}
override fun onResume() {
super.onResume()
- if (serviceHasBeenSet && service == null || service != null && !service?.isGattConnected(connectionAddress)!!) {
+ if (serviceHasBeenSet && service == null || service != null && !service?.isGattConnected(
+ connectionAddress
+ )!!
+ ) {
onDeviceDisconnected()
}
}
private fun onTabClick(isFahrenheitUnit: Boolean) {
- currentType = if (isFahrenheitUnit) TemperatureReading.Type.FAHRENHEIT else TemperatureReading.Type.CELSIUS
- thermo_large_temperature.setCurrentType(currentType)
+ currentType =
+ if (isFahrenheitUnit) TemperatureReading.Type.FAHRENHEIT else TemperatureReading.Type.CELSIUS
+ binding.thermoLargeTemperature.setCurrentType(currentType)
}
fun setCurrentReading(temperatureReading: TemperatureReading?) {
@@ -113,14 +139,17 @@ class HealthThermometerActivity : BaseDemoActivity() {
private fun refreshUi() {
if (currentReading != null) {
- thermo_large_temperature?.setTemperature(currentReading)
- thermo_type_value_text?.text = getString(currentReading?.htmType?.nameResId!!)
- thermo_type_value?.text = getString(R.string.temperature_type,
- getString(currentReading?.htmType?.nameResId!!))
- thermo_large_time_text?.text = currentReading?.getFormattedTime()
+ binding.thermoLargeTemperature.setTemperature(currentReading)
+ binding.thermoTypeValueText.text = getString(currentReading?.htmType?.nameResId!!)
+ binding.thermoTypeValue.text = getString(R.string.temperature_type,
+ getString(currentReading?.htmType?.nameResId!!))
+
+ binding.thermoLargeTimeText.text = currentReading?.getFormattedTime()
}
}
+ //private fun textView(): TextView = binding.thermoTypeValue.text
+
override fun onBluetoothServiceBound() {
serviceHasBeenSet = true
service?.registerGattCallback(true, gattCallback)
@@ -130,7 +159,8 @@ class HealthThermometerActivity : BaseDemoActivity() {
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
//When you switch thermometers, this activity should get a new intent - at this point, we hide the dialog
- val dialog = supportFragmentManager.findFragmentByTag("select_device_tag") as SelectDeviceDialog?
+ val dialog =
+ supportFragmentManager.findFragmentByTag("select_device_tag") as SelectDeviceDialog?
if (dialog != null && dialog.isVisible) {
dialog.dismiss()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/activities/MatterDemoActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/activities/MatterDemoActivity.kt
index 7968cf26..de2320cc 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/activities/MatterDemoActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/activities/MatterDemoActivity.kt
@@ -12,8 +12,7 @@ import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.GetConnectedDeviceCallbackJni
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.databinding.ActivityMatterDemoBinding
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterConnectFragment
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterConnectFragment.Companion.DIA_INPUT_NTW_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterDishwasherFragment
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterDoorFragment
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterOccupancySensorFragment
@@ -22,26 +21,23 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScanner
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterThermostatFragment
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterWifiInputDialogFragment
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterWindowCoverFragment
-import com.siliconlabs.bledemo.features.demo.matter_demo.model.CHIPDeviceInfo
import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
import com.siliconlabs.bledemo.features.demo.matter_demo.model.ProvisionNetworkType
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
-import kotlinx.android.synthetic.main.activity_matter_demo.refresh
-import kotlinx.android.synthetic.main.activity_matter_demo.scanQRCode
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
+import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
class MatterDemoActivity : AppCompatActivity(),
MatterScannerFragment.CallBack,
- MatterConnectFragment.Callback,
MatterScannedResultFragment.Callback,
MatterThermostatFragment.CallBackHandler,
MatterLightFragment.CallBackHandler,
@@ -53,18 +49,18 @@ class MatterDemoActivity : AppCompatActivity(),
private var currentFragment: Fragment? = null
private lateinit var binding: ActivityMatterDemoBinding
- private var deviceInfo: CHIPDeviceInfo? = null
private var scannedDeviceList = ArrayList()
private lateinit var mPrefs: SharedPreferences
- private var chipDeviceList: ArrayList = ArrayList()
private lateinit var deviceController: ChipDeviceController
private var customProgressDialog: CustomProgressDialog? = null
private var networkType: ProvisionNetworkType? = null
private var shouldContinueOperation = true
private var count: Int = 0
+
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- Timber.tag(TAG).e( " oncreate")
+ Timber.tag(TAG).e(" onCreate")
binding = ActivityMatterDemoBinding.inflate(layoutInflater)
mPrefs = this.getSharedPreferences("your_preference_name", MODE_PRIVATE)
setSupportActionBar(binding.toolbar)
@@ -72,24 +68,23 @@ class MatterDemoActivity : AppCompatActivity(),
deviceController = ChipClient.getDeviceController(this)
val actionBar = supportActionBar
- actionBar!!.setHomeAsUpIndicator(R.drawable.matter_back)
- actionBar.setDisplayHomeAsUpEnabled(true)
-
- scanQRCode.setOnClickListener {
+ if (actionBar != null) {
+ actionBar.setHomeAsUpIndicator(R.drawable.matter_back)
+ actionBar.setDisplayHomeAsUpEnabled(true)
+ }
+ binding.scanQRCode.setOnClickListener {
val fragment = MatterScannerFragment.newInstance()
showFragment(
- fragment, true, fragment::class.java.simpleName,
- fragment::class.java.simpleName
+ fragment, fragment::class.java.simpleName
)
}
-
- refresh.setOnClickListener {
+ binding.refresh.setOnClickListener {
count = 0
if (SharedPrefsUtils.retrieveSavedDevices(mPrefs).size > 0) {
showMatterProgressDialog(getString(R.string.matter_device_status))
- GlobalScope.launch {
- val resultq = performLongRunningOperation()
- if (resultq) {
+ CoroutineScope(Dispatchers.Default).launch {
+ val resultInfo = performLongRunningOperation()
+ if (resultInfo) {
println("Operation was successful")
removeProgress()
scannedDeviceList = SharedPrefsUtils.retrieveSavedDevices(mPrefs)
@@ -106,7 +101,7 @@ class MatterDemoActivity : AppCompatActivity(),
}
private fun startPeriodictFunction() {
- GlobalScope.launch(Dispatchers.Default) {
+ CoroutineScope(Dispatchers.Default).launch {
while (shouldContinueOperation) {
performLongRunningOperation() // Call your long-running operation
delay(DELAY_TIMEOUT)
@@ -140,27 +135,28 @@ class MatterDemoActivity : AppCompatActivity(),
customProgressDialog = CustomProgressDialog(this)
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.show()
}
override fun onResume() {
super.onResume()
- Timber.tag(TAG).e( " on resume")
+ Timber.tag(TAG).e(" on resume")
count = 0
}
override fun onStart() {
super.onStart()
- Timber.tag(TAG).e( " onStart")
+ Timber.tag(TAG).e(" onStart")
}
- private suspend fun performLongRunningOperation(): Boolean {
- GlobalScope.launch {
+ private fun performLongRunningOperation(): Boolean {
+ CoroutineScope(Dispatchers.IO).launch {
val savedDevices = SharedPrefsUtils.retrieveSavedDevices(mPrefs)
- for ((index, item) in savedDevices.withIndex()) {
+ for (item in savedDevices) {
getStatus(item.deviceId)
}
}
@@ -173,12 +169,12 @@ class MatterDemoActivity : AppCompatActivity(),
println("Matter Total device found $savedDeviceCount")
try {
+ // suspendCoroutine { continuation ->
suspendCoroutine { continuation ->
deviceController.getConnectedDevicePointer(deviceId,
object : GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback {
override fun onDeviceConnected(devicePointer: Long) {
- //Timber.tag(TAG).e("-------------------------------")
Timber.tag(TAG).e("devicePointer $devicePointer")
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
if (currentFragment != null) {
@@ -193,17 +189,17 @@ class MatterDemoActivity : AppCompatActivity(),
if (count >= savedDeviceCount) {
removeProgress()
}
+ // continuation.resume(Unit)
}
override fun onConnectionFailure(
nodeId: Long,
error: java.lang.Exception?
) {
-
- //Timber.tag(TAG).e("-------------------------------")
Timber.tag(TAG).e("nodeId $nodeId Error $error")
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
- currentFragment = supportFragmentManager.findFragmentById(R.id.matter_container)
+ currentFragment =
+ supportFragmentManager.findFragmentById(R.id.matter_container)
if (currentFragment != null) {
when (currentFragment) {
is MatterScannedResultFragment -> {
@@ -229,7 +225,6 @@ class MatterDemoActivity : AppCompatActivity(),
}
-
override fun onDestroy() {
super.onDestroy()
stopPeriodicOperation()
@@ -246,8 +241,7 @@ class MatterDemoActivity : AppCompatActivity(),
}
private fun showFragment(
- fragment: Fragment, addToBackStack: Boolean = true,
- fragmentName: String? = null, tag: String? = null,
+ fragment: Fragment, tag: String? = null,
) {
val fManager = supportFragmentManager
val fTransaction = fManager.beginTransaction()
@@ -259,32 +253,12 @@ class MatterDemoActivity : AppCompatActivity(),
}
- override fun onChipDeviceInfoReceived(deviceInfo: CHIPDeviceInfo, ntwInputType: String) {
- Timber.tag(TAG).e(" onChipDeviceInfoReceived")
- deviceInfo.networkType = ntwInputType
- this.deviceInfo = deviceInfo
- chipDeviceList.add(deviceInfo)
-
- val bundle = Bundle()
- bundle.putParcelable(ARG_DEVICE_INFO, deviceInfo)
- bundle.putString(DIA_INPUT_NTW_TYPE, ntwInputType)
- val fragment = MatterConnectFragment.newInstance()
- fragment.arguments = bundle
- showFragment(
- fragment, true, fragment::class.java.simpleName,
- fragment::class.java.simpleName
- )
- }
-
override fun onSaveInstanceState(outState: Bundle) {
outState.putString(MatterScannerFragment.ARG_PROVISION_NETWORK_TYPE, networkType?.name)
super.onSaveInstanceState(outState)
}
- override fun setNetworkType(type: ProvisionNetworkType) {
- //ignore
- }
override fun onCommissionCompleteLoadData(matterScannedResultModel: MatterScannedResultModel) {
Timber.tag(TAG).e("on commission complete add $matterScannedResultModel ")
@@ -352,7 +326,18 @@ class MatterDemoActivity : AppCompatActivity(),
this.finish()
- } else if (supportFragmentManager.backStackEntryCount > 0) {
+ }else if (currentFragment != null && currentFragment is MatterDishwasherFragment) {
+
+ val fragment = supportFragmentManager.findFragmentById(R.id.matter_container) as? MatterDishwasherFragment
+
+ fragment?.let {
+ // You can access the DataBinding object here
+ // Example: Change the text of the TextView inside the fragment when back is pressed
+ it.handleDishwasherBackNavigationUI()
+ }
+
+ }
+ else if (supportFragmentManager.backStackEntryCount > 0) {
supportFragmentManager.popBackStack()
} else {
this.finish()
@@ -365,10 +350,10 @@ class MatterDemoActivity : AppCompatActivity(),
}
companion object {
- private const val ARG_DEVICE_INFO = "device_info"
private const val TAG = "MatterDemoActivity"
private const val ARG_DEVICE_LIST = "device_list"
private const val ARG_DEVICE_MODEL = "device_model"
private const val DELAY_TIMEOUT = 8000L
+ const val MATTER_PREF = "your_preference_name"
}
}
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 fe06c239..3ae188dc 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,12 +1,10 @@
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
@@ -38,37 +36,38 @@ class MatterScannedResultAdapter(
holder.itemView.isEnabled = true
holder.itemView.isClickable = true
- holder.itemView.alpha = 1.0f // Set alpha to 1 for enabled rows
+ holder.binding.root.alpha = 1.0f // Set alpha to 1 for enabled rows
} else {
- holder.binding.imageview.setColorFilter(
+ holder.binding.root.alpha = 0.5f
+ holder.binding.imageView.setColorFilter(
ContextCompat.getColor(context, R.color.silabs_dark_gray_icon),
android.graphics.PorterDuff.Mode.SRC_IN
)
holder.itemView.isEnabled = false
holder.itemView.isClickable = false
- holder.itemView.alpha = 0.5f // Set alpha to 0.5 for disabled rows
- holder.itemView.setBackgroundColor(ContextCompat.getColor(context, R.color.silabs_inactive_light));
- holder.binding.cardView.setBackgroundColor(ContextCompat.getColor(context, R.color.silabs_inactive_light));
- holder.binding.itemViewHolder.setBackgroundColor(ContextCompat.getColor(context, R.color.silabs_inactive_light));
- holder.binding.imageview.setBackgroundColor(ContextCompat.getColor(context, R.color.silabs_inactive_light));
-
+ // Set alpha to 0.5 for disabled rows
+// holder.itemView.setBackgroundColor(ContextCompat.getColor(context, R.color.silabs_inactive_light));
+// holder.binding.cardView.setBackgroundColor(ContextCompat.getColor(context, R.color.silabs_inactive_light));
+// holder.binding.itemViewHolder.setBackgroundColor(ContextCompat.getColor(context, R.color.silabs_inactive_light));
+// holder.binding.imageView.setBackgroundColor(ContextCompat.getColor(context, R.color.silabs_inactive_light));
}
- // holder.binding.imgDelete.setVisibility(View.GONE);
- holder.binding.swipe.setShowMode(SwipeLayout.ShowMode.PullOut);
+ holder.binding.swipe.setShowMode(SwipeLayout.ShowMode.LayDown);
holder.binding.swipe.addDrag(
SwipeLayout.DragEdge.Right,
holder.binding.swipe.findViewById(R.id.bottom_wrapper)
)
- //viewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Right, viewHolder.swipeLayout.findViewById(R.id.bottom_wrapper));
- holder.binding.itemViewHolder.setOnClickListener {
- runBlocking {
- if (onClickListener != null) {
- onClickListener!!.onClick(position, matterInfo)
+ holder.binding.itemViewHolder.setOnClickListener {
+ if (matterInfo.isDeviceOnline){
+ runBlocking {
+ if (onClickListener != null) {
+ onClickListener!!.onClick(position, matterInfo)
+ }
}
+ }else{
+ return@setOnClickListener
}
-
}
holder.binding.imgDelete.setOnClickListener {
runBlocking {
@@ -89,7 +88,6 @@ class MatterScannedResultAdapter(
interface OnClickListener {
suspend fun onClick(position: Int, model: MatterScannedResultModel)
- // suspend fun simpleCallback(position: Int, model: MatterScannedResultModel)
suspend fun onDelete(position: Int, model: MatterScannedResultModel)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/controller/GenericChipDeviceListener.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/controller/GenericChipDeviceListener.kt
index 15cd1653..98506372 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/controller/GenericChipDeviceListener.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/controller/GenericChipDeviceListener.kt
@@ -1,54 +1,57 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.controller
import chip.devicecontroller.ChipDeviceController
+import chip.devicecontroller.ICDDeviceInfo
-open class GenericChipDeviceListener: ChipDeviceController.CompletionListener {
+open class GenericChipDeviceListener : ChipDeviceController.CompletionListener {
override fun onConnectDeviceComplete() {
- // No op
+
}
override fun onStatusUpdate(status: Int) {
- // No op
}
- override fun onPairingComplete(errorCode: Int) {
- // No op
+ override fun onPairingComplete(errorCode: Long) {
}
- override fun onPairingDeleted(errorCode: Int) {
- // No op
+ override fun onPairingDeleted(errorCode: Long) {
+
}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
}
+
override fun onReadCommissioningInfo(
vendorId: Int,
productId: Int,
wifiEndpointId: Int,
threadEndpointId: Int
) {
- // No op
}
- override fun onCommissioningStatusUpdate(nodeId: Long, stage: String?, errorCode: Int) {
- // No op
+ override fun onCommissioningStatusUpdate(nodeId: Long, stage: String?, errorCode: Long) {
+
}
override fun onNotifyChipConnectionClosed() {
- // No op
}
override fun onCloseBleComplete() {
- // No op
}
- override fun onError(error: Throwable) {
- // No op
+ override fun onError(error: Throwable?) {
+ }
+
+ override fun onOpCSRGenerationComplete(csr: ByteArray?) {
+ }
+
+ override fun onICDRegistrationInfoRequired() {
}
- override fun onOpCSRGenerationComplete(csr: ByteArray) {
- // No op
+ override fun onICDRegistrationComplete(errorCode: Long, icdDeviceInfo: ICDDeviceInfo?) {
}
+
+
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterConnectFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterConnectFragment.kt
deleted file mode 100644
index e3e6172f..00000000
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterConnectFragment.kt
+++ /dev/null
@@ -1,725 +0,0 @@
-package com.siliconlabs.bledemo.features.demo.matter_demo.fragments
-
-import android.annotation.SuppressLint
-import android.app.Activity
-import android.app.AlertDialog
-import android.bluetooth.BluetoothDevice
-import android.bluetooth.BluetoothGatt
-import android.content.DialogInterface
-import android.content.Intent
-import android.graphics.Color
-import android.graphics.drawable.ColorDrawable
-import android.os.Build
-import android.os.Bundle
-import android.os.Handler
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Toast
-import androidx.annotation.RequiresApi
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentTransaction
-import androidx.lifecycle.lifecycleScope
-import chip.devicecontroller.ChipClusters
-import chip.devicecontroller.ChipDeviceController
-import chip.devicecontroller.ChipStructs
-import chip.devicecontroller.NetworkCredentials
-import com.siliconlabs.bledemo.R
-import com.siliconlabs.bledemo.databinding.FragmentMatterConnectBinding
-import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoActivity
-import com.siliconlabs.bledemo.features.demo.matter_demo.controller.GenericChipDeviceListener
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.CONTACT_SENSOR_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.LIGHTNING_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.LOCK_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.OCCUPANCY_SENSOR_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.PLUG_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.TEMPERATURE_SENSOR_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.THERMOSTAT_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.WINDOW_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannerFragment.Companion.INPUT_NETWORK_THREAD_TYPE_SELECTED
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannerFragment.Companion.INPUT_NETWORK_WIFI_TYPE_SELECTED
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannerFragment.Companion.INPUT_WIFI_REQ_CODE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannerFragment.Companion.WIFI_INPUT_PASSWORD
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannerFragment.Companion.WIFI_INPUT_SSID
-import com.siliconlabs.bledemo.features.demo.matter_demo.manager.BluetoothManager
-import com.siliconlabs.bledemo.features.demo.matter_demo.model.CHIPDeviceInfo
-import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
-import com.siliconlabs.bledemo.features.demo.matter_demo.model.NetworkCredentialsParcelable
-import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
-import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomInputDialog
-import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
-import com.siliconlabs.bledemo.features.demo.matter_demo.utils.DeviceIDUtil
-import com.siliconlabs.bledemo.features.demo.matter_demo.utils.FragmentUtils
-import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFragment
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-import timber.log.Timber
-
-
-class MatterConnectFragment : Fragment() {
- private val channelInfo: String = "15"
- private val panId: String = "1234"
- private var customProgressDialog: CustomProgressDialog? = null
-
- private lateinit var extentedPanId: String
- private lateinit var masterKey: String
-
- private lateinit var binding: FragmentMatterConnectBinding
- private lateinit var deviceController: ChipDeviceController
- private lateinit var scope: CoroutineScope
- private lateinit var deviceInfo: CHIPDeviceInfo
- private var gatt: BluetoothGatt? = null
- private lateinit var bluetoothManager: BluetoothManager
- private lateinit var networkCredential: NetworkCredentialsParcelable
- private lateinit var matterScanDevice: BluetoothDevice
- private var deviceId: Long = 0;
-
- private var dialog: AlertDialog? = null
- private var otbrEntryDialog: MatterOTBRInputDialogFragment? = null
- private var wifiEntryDialog: MatterWifiInputDialogFragment? = null
- private lateinit var typeNtw: String
-
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- deviceController = ChipClient.getDeviceController(requireContext())
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- super.onCreateView(inflater, container, savedInstanceState)
- scope = viewLifecycleOwner.lifecycleScope
- if (requireArguments() != null) {
- typeNtw = checkNotNull(requireArguments().getString(DIA_INPUT_NTW_TYPE))
- deviceInfo = checkNotNull(requireArguments().getParcelable(ARG_DEVICE_INFO))
- }
- binding = FragmentMatterConnectBinding.inflate(inflater, container, false)
- return binding.root
- }
-
-
- @RequiresApi(Build.VERSION_CODES.R)
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- (activity as MatterDemoActivity).showQRScanner()
-
- val str = requireContext().getString(R.string.matter_commissioning_device)
- showMatterProgressDialog(str)
- Handler().postDelayed(Runnable {
- removeProgress()
- displayInputWindowBasedOnProvisionType()
- }, 1000)
- }
-
- private fun removeProgress() {
- if (customProgressDialog?.isShowing == true) {
- customProgressDialog?.dismiss()
- }
- }
-
- private fun displayInputWindowBasedOnProvisionType() {
- when (typeNtw) {
- INPUT_NETWORK_WIFI_TYPE_SELECTED /* ProvisionNetworkType.WIFI */ -> {
- if (wifiEntryDialog == null) {
- val prev =
- requireActivity().supportFragmentManager.findFragmentByTag(
- DIALOG_WIFI_INPUT_TAG
- )
- if (prev == null) {
- wifiEntryDialog = MatterWifiInputDialogFragment.newInstance()
- wifiEntryDialog!!.setTargetFragment(this, DIALOG_WIFI_FRAGMENT)
- wifiEntryDialog!!.show(
- requireActivity().supportFragmentManager,
- DIALOG_WIFI_INPUT_TAG
- )
- }
- }
- }
-
- INPUT_NETWORK_THREAD_TYPE_SELECTED /* ProvisionNetworkType.THREAD*/ -> {
- if (otbrEntryDialog == null) {
- val prev =
- requireActivity().supportFragmentManager.findFragmentByTag(
- DIALOG_THREAD_INPUT_TAG
- )
- if (prev == null) {
- otbrEntryDialog = MatterOTBRInputDialogFragment.newInstance()
-
- otbrEntryDialog!!.setTargetFragment(this, DIALOG_THREAD_FRAGMENT)
- otbrEntryDialog!!.show(
- requireActivity().supportFragmentManager,
- DIALOG_THREAD_INPUT_TAG
- )
- }
- }
- }
-
- else -> {
- println("Unhandled....")
- }
-
- }
- }
-
- @RequiresApi(Build.VERSION_CODES.R)
- private fun validateWiFiInput(wifiSSID: String, wifiPassword: String) {
- networkCredential = NetworkCredentialsParcelable
- .forWiFi(
- NetworkCredentialsParcelable.WiFiCredentials(
- wifiSSID.toString(), wifiPassword.toString()
- )
- )
- // pairDeviceWithAddress()
- startConnectingToDevice()
- }
-
- @SuppressLint("NewApi")
- private fun validateThreadInput(inputOTBR: String) {
- if (inputOTBR.isNullOrBlank()) {
- Toast.makeText(requireContext(), "input OTBR is empty", Toast.LENGTH_SHORT).show()
- return
- }
- val operationalDataset = dataFromHexString(inputOTBR.trim())
-
- networkCredential = NetworkCredentialsParcelable
- .forThread(NetworkCredentialsParcelable.ThreadCredentials(operationalDataset))
- startConnectingToDevice()
- }
-
- @RequiresApi(Build.VERSION_CODES.R)
- private fun validateInputOld(input: String) {
-// if (input.isNullOrBlank()) {
-// Toast.makeText(requireContext(), "input OTBR is empty", Toast.LENGTH_SHORT).show()
-// return
-// }
-
- //--------------------------------------------------------
- //Old Setup Supported Code
- extentedPanId = resources.getString(R.string.extPanID)
- masterKey = resources.getString(R.string.matMasterKey)
- if (channelInfo.isNullOrBlank()) {
- Toast.makeText(requireContext(), "Channel is empty", Toast.LENGTH_SHORT).show()
- return
- }
-
- if (panId.isNullOrBlank()) {
- Toast.makeText(requireContext(), "PAN ID is empty", Toast.LENGTH_SHORT).show()
- return
- }
-
- if (extentedPanId.isNullOrBlank()) {
- Toast.makeText(requireContext(), "XPAN ID is empty", Toast.LENGTH_SHORT).show()
- return
- }
- val extendedPanIDStr = extentedPanId.toString().filterNot { c -> c == ':' }
- if (extendedPanIDStr.length != NUM_XPANID_BYTES * 2) {
- Toast.makeText(requireContext(), "Extended PAN ID is invalid", Toast.LENGTH_SHORT)
- .show()
- return
- }
-
- if (masterKey.isNullOrBlank()) {
- Toast.makeText(requireContext(), "Master Key is empty", Toast.LENGTH_SHORT).show()
- return
- }
-
- val masterKeyStr = masterKey.toString().filterNot { c -> c == ':' }
- if (masterKeyStr.length != NUM_MASTER_KEY_BYTES * 2) {
- Toast.makeText(requireContext(), "Master key is invalid", Toast.LENGTH_SHORT).show()
- return
- }
- val extPID = extendedPanIDStr.hexToByteArray()
- val masKey = masterKeyStr.hexToByteArray()
-
- val operationalDataset = makeThreadOperationalDataset(
- channelInfo.toInt(),
- panId.toInt(16),
- extPID,
- masKey
- )
- println(
- "OperationDataSet ${operationalDataset.size}"
- )
- //--------------------------------------------------------
-
- // val operationalDataset = dataFromHexString(input.trim())
- networkCredential = NetworkCredentialsParcelable
- .forThread(NetworkCredentialsParcelable.ThreadCredentials(operationalDataset))
- startConnectingToDevice()
- }
-
-
- private fun convertInputToByteArray(strInput: String): ByteArray {
- return strInput.toByteArray()
- }
-
- private fun makeThreadOperationalDataset(
- channel: Int,
- panId: Int,
- xpanId: ByteArray,
- masterKey: ByteArray
- ): ByteArray {
-
- // channel
- var dataset = byteArrayOf(TYPE_CHANNEL.toByte(), NUM_CHANNEL_BYTES.toByte())
- dataset += 0x00.toByte() // Channel Page 0.
- dataset += (channel.shr(8) and 0xFF).toByte()
- dataset += (channel and 0xFF).toByte()
-
- // PAN ID
- dataset += TYPE_PANID.toByte()
- dataset += NUM_PANID_BYTES.toByte()
- dataset += (panId.shr(8) and 0xFF).toByte()
- dataset += (panId and 0xFF).toByte()
-
- // Extended PAN ID
- dataset += TYPE_XPANID.toByte()
- dataset += NUM_XPANID_BYTES.toByte()
- dataset += xpanId
-
- // Network Master Key
- dataset += TYPE_MASTER_KEY.toByte()
- dataset += NUM_MASTER_KEY_BYTES.toByte()
- dataset += masterKey
- Timber.tag(TAG).e("dataset " + dataset.decodeToString())
-
- return dataset
- }
-
-
- private fun String.hexToByteArray(): ByteArray {
- return chunked(2).map { byteStr -> byteStr.toUByte(16).toByte() }.toByteArray()
- }
-
-
- @RequiresApi(Build.VERSION_CODES.R)
- @SuppressLint("MissingPermission")
- private fun startConnectingToDevice() {
- if (gatt != null) {
- return
- }
- scope.launch {
-
- bluetoothManager = BluetoothManager()
- val strId = R.string.rendezvous_over_ble_scanning_text
- val devInfo = deviceInfo.discriminator.toString()
- showMessage(strId, devInfo)
- val device = bluetoothManager.getBluetoothDevice(
- requireContext(),
- deviceInfo.discriminator, deviceInfo.isShortDiscriminator
- ) ?: kotlin.run {
- requireActivity().supportFragmentManager.popBackStack()
- requireActivity().supportFragmentManager.popBackStack()
-
- showMessage(R.string.rendezvous_over_ble_scanning_failed_text)
- return@launch
- }
- matterScanDevice = device
- Timber.tag(TAG).e("Type :" + device.type.toString())
- Timber.tag(TAG).e("UUID :" + device.uuids.toString())
- Timber.tag(TAG).e("Name :" + device.name.toString())
- Timber.tag(TAG).e("Address :" + device.address.toString())
- Timber.tag(TAG).e("Alias :" + device.alias.toString())
- showMatterProgressDialog(getString(R.string.device_commissioning_in_progress) + " " + device.name)
-
-
- showMessage(
- R.string.rendezvous_over_ble_connecting_text,
- device.name ?: device.address.toString()
- )
- removeAlert()
- deviceId = DeviceIDUtil.getNextAvailableId(requireContext())
- gatt = bluetoothManager.connect(requireContext(), device)
- deviceController.setCompletionListener(ConnectionCallback())
- val connId = bluetoothManager.connectionId
- var network: NetworkCredentials? = null
-
-
- val thread = networkCredential.threadCredentials
- if (thread != null) {
- network =
- NetworkCredentials.forThread(
- NetworkCredentials.ThreadCredentials(thread.operationalDataset)
- )
- }
- val wifi = networkCredential.wiFiCredentials
- if (wifi != null) {
- network =
- NetworkCredentials.forWiFi(
- NetworkCredentials.WiFiCredentials(wifi.ssid, wifi.password)
- )
- }
-
- setAttestationDelegate()
-
- deviceController.pairDevice(
- gatt,
- connId,
- deviceId,
- deviceInfo.setupPinCode,
- network
- )
- DeviceIDUtil.setNextAvailableId(requireContext(), deviceId + 1)
- }
- }
-
- private fun showMatterProgressDialog(message: String) {
-
- customProgressDialog = CustomProgressDialog(requireContext())
- customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
- customProgressDialog!!.setMessage(message)
- customProgressDialog!!.show()
- }
-
- private fun setAttestationDelegate() {
- deviceController.setDeviceAttestationDelegate(DEVICE_ATTESTATION_FAILED_TIMEOUT) { devicePtr, _, errorCode ->
-
- Timber.tag(TAG).e(
- "Device attestation errorCode: $errorCode, " +
- "Look at 'src/credentials/attestation_verifier/DeviceAttestationVerifier.h' " +
- "AttestationVerificationResult enum to understand the errors"
- )
- val activity = requireActivity()
- Timber.tag(TAG).e("setAttestationDelegate()--errorCode:" + errorCode)
- if (errorCode == STATUS_PAIRING_SUCCESS) {
- Timber.tag(TAG).e("setAttestationDelegate() In--errorCode:" + errorCode)
- activity.runOnUiThread(Runnable {
- deviceController.continueCommissioning(devicePtr, true)
- })
-
- return@setDeviceAttestationDelegate
- }
- activity.runOnUiThread(Runnable {
- if (dialog != null && dialog?.isShowing == true) {
- Timber.tag(TAG).e("Dialog is already showing...")
- return@Runnable
- }
- dialog = AlertDialog.Builder(activity)
- .setPositiveButton("Continue",
- DialogInterface.OnClickListener { dialog, id ->
- deviceController.continueCommissioning(devicePtr, true)
- })
- .setNegativeButton("No",
- DialogInterface.OnClickListener { dialog, id ->
- deviceController.continueCommissioning(devicePtr, false)
- })
- .setTitle("Device Attestation")
- .setMessage("Device Attestation failed for device under commissioning. Do you wish to continue pairing?")
- .show()
- })
-
- }
- }
-
- private fun removeAlert() {
- if (otbrEntryDialog != null) {
- otbrEntryDialog!!.dismiss()
- }
- }
-
- private fun onCommissionCompleted() {
- ChipClient.getDeviceController(requireContext()).close()
- }
-
- inner class ConnectionCallback : GenericChipDeviceListener() {
- override fun onConnectDeviceComplete() {
- super.onConnectDeviceComplete()
- Timber.tag(TAG).e("onConnectDeviceComplete")
- }
-
- override fun onStatusUpdate(status: Int) {
- super.onStatusUpdate(status)
- Timber.tag(TAG).e("onStatusUpdate : $status.toString()")
- }
-
-
- @SuppressLint("MissingPermission")
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
- super.onCommissioningComplete(nodeId, errorCode)
- Timber.tag(TAG).e("onCommissioningComplete : NodeID: $nodeId.toString()")
- Timber.tag(TAG).e("onCommissioningComplete : errorCode: " + errorCode.toString())
- removeAlert()
- if (errorCode == STATUS_PAIRING_SUCCESS) {
- if (customProgressDialog?.isShowing == true) {
- customProgressDialog?.dismiss()
- }
- Timber.tag(TAG).e("pairing success")
- onCommissionCompleted()
-
- scope.launch {
- getDescriptorClusterForDevice().readDeviceTypeListAttribute(object :
- ChipClusters.DescriptorCluster.DeviceTypeListAttributeCallback {
- override fun onSuccess(valueList: MutableList?) {
-
- Timber.tag(TAG)
- .e("deviceType $ valueList?.get(0)?.deviceType?.toInt()!!")
- val deviceType = valueList?.get(0)?.deviceType?.toInt()!!
- println("device Type: $deviceType}")
- println("device Info: ${matterScanDevice.name} DeviceId: ${deviceId}")
- var device: String = ""
-
- when (deviceType) {
- LOCK_TYPE ->
- device =
- requireContext().getString(R.string.matter_lock_list)
-
- PLUG_TYPE ->
- device =
- requireContext().getString(R.string.matter_plug_list)
-
- OCCUPANCY_SENSOR_TYPE ->
- device =
- requireContext().getString(R.string.matter_occupancy_sensor_list)
-
- TEMPERATURE_SENSOR_TYPE ->
- device =
- requireContext().getString(R.string.matter_temperature_sensor_list)
-
- CONTACT_SENSOR_TYPE ->
- device =
- requireContext().getString(R.string.matter_contact_sensor_list)
-
- THERMOSTAT_TYPE ->
- device =
- requireContext().getString(R.string.matter_thermostat_list)
-
- LIGHTNING_TYPE ->
- device =
- requireContext().getString(R.string.matter_light_list)
-
- WINDOW_TYPE ->
- device =
- requireContext().getString(R.string.matter_window_list)
-
- else -> device = matterScanDevice.name
-
-
- // else -> device = matterScanDevice.name
- }
-
- val deviceName = device + COLON_WITH_SPACE + deviceId
- println("device Info: ${deviceName} DeviceId: ${deviceId}")
-
- ShowEditDeviceNameDialog(device, valueList)
-
-
- }
-
- private fun ShowEditDeviceNameDialog(
- device: String,
- valueList: MutableList
- ) {
-
- val customInputDialog = CustomInputDialog.newInstance(
- requireContext(), device, getString(R.string.add_device_name),
- getString(
- R.string.add_device_subtitle
- )
- )
-
-
- customInputDialog.setOnButtonClickListener { deviceName ->
-
- val matterInfo = MatterScannedResultModel(
- deviceName,
- matterScanDevice.address,
- matterScanDevice.type,
- deviceId,
- valueList?.get(0)?.deviceType?.toInt()!!,
- isDeviceOnline = true
- )
- FragmentUtils.getHost(
- this@MatterConnectFragment,
- Callback::
- class.java
- )
- .onCommissionCompleteLoadData(matterInfo)
-
- }
-
- customInputDialog.show(requireFragmentManager(), "CustomInputDialog")
-
-
- }
-
- override fun onError(ex: Exception?) {
- Timber.tag(TAG).e("failed to read readDeviceTypeListAttribute" + ex)
- }
- })
- }
-
-
- } else {
- if (customProgressDialog?.isShowing() == true) {
- customProgressDialog?.dismiss()
- }
-
- /*val strId = R.string.matter_device_offline_text
- showMessages(strId)*/
- }
- onCommissionCompleted()
- }
-
- override fun onPairingComplete(errorCode: Int) {
- super.onPairingComplete(errorCode)
- Timber.tag(TAG).e("onPairingComplete: $errorCode")
- if (errorCode != STATUS_PAIRING_SUCCESS) {
- showMessage(R.string.rendezvous_over_ble_pairing_failure_text)
- onCommissionCompleted()
- }
- }
-
- override fun onOpCSRGenerationComplete(csr: ByteArray) {
- super.onOpCSRGenerationComplete(csr)
- Timber.tag(TAG).e(String(csr))
- }
-
- override fun onPairingDeleted(errorCode: Int) {
- super.onPairingDeleted(errorCode)
- Timber.tag(TAG).e("onPairingDeleted: $errorCode")
- }
-
- override fun onCloseBleComplete() {
- super.onCloseBleComplete()
- Timber.tag(TAG).e("onCloseBleComplete")
- }
-
- override fun onError(error: Throwable) {
- super.onError(error)
- Timber.tag(TAG).d("onError: $error")
- }
- }
-
-
- private fun showMessages(msgId: Int) {
- requireActivity().runOnUiThread {
- val resString = requireContext().getString(msgId)
- Toast.makeText(requireContext(), resString, Toast.LENGTH_SHORT).show()
- }
- }
-
- private fun showMessage(msgResId: Int, stringArgs: String? = null) {
- requireActivity().runOnUiThread {
- val context = requireContext()
- val msg = context.getString(msgResId, stringArgs)
- Timber.tag(TAG).e("showMessage:$msg")
- Toast.makeText(context, msg, Toast.LENGTH_SHORT)
- .show()
- }
- }
-
- @RequiresApi(Build.VERSION_CODES.R)
- override fun onActivityResult(requestCode: Int, resultCode: Int, dataReceived: Intent?) {
- super.onActivityResult(requestCode, resultCode, dataReceived)
- if (resultCode == Activity.RESULT_OK) {
- if (dataReceived != null) {
- val receiveOTBRInfo = dataReceived.getStringExtra(DIALOG_OTBR_INFO)
-
- println("OTBR data: $receiveOTBRInfo")
- removeAlert()
- validateThreadInput(receiveOTBRInfo!!.trim())
- }
- } else if (resultCode == INPUT_WIFI_REQ_CODE) {
- if (dataReceived != null) {
- val wifiSSID = dataReceived.getStringExtra(WIFI_INPUT_SSID)
- val wifiPassword = dataReceived.getStringExtra(WIFI_INPUT_PASSWORD)
- println("wifiSSID: ${wifiSSID} === wifiPassword:${wifiPassword}")
- if (wifiSSID != null && wifiPassword != null) {
- validateWiFiInput(wifiSSID, wifiPassword)
- }
- }
- }
- }
-
- override fun onDestroy() {
- super.onDestroy()
- deviceController.close()
- }
-
-
- interface Callback {
- fun onCommissionCompleteLoadData(matterScannedResultModel: MatterScannedResultModel)
- }
-
- private suspend fun getDescriptorClusterForDevice(): ChipClusters.DescriptorCluster {
- return ChipClusters.DescriptorCluster(
-
- ChipClient.getConnectedDevicePointer(requireContext(), deviceId),
- ON_OFF_CLUSTER_ENDPOINT
- )
- }
-
-
- private fun dataFromHexString(string: String): ByteArray {
- var modifiedString = string
- if (string.length % 2 == 1) {
- modifiedString = "0$string"
- }
-
- val chars = modifiedString.toCharArray()
- var i = 0
- val len = modifiedString.length
-
-
- val data = ByteArray(len / 2)
- val byteChars = CharArray(2)
-
-
- while (i < len) {
- byteChars[0] = chars[i++]
- byteChars[1] = chars[i++]
- var wholeByte = 0L
- try {
- wholeByte = byteChars.joinToString("").toLong(16)
-
- } catch (ex: NumberFormatException) {
- var wholeByte = 0L
- Timber.tag(TAG).e("Number Format Exception Occurred..")
- }
-
- data[(i - 2) / 2] = wholeByte.toByte()
- }
-
- return data
- }
-
-
- companion object {
- private val TAG = "MatterConnectFragment"
- private const val ARG_DEVICE_INFO = "device_info"
- private const val NUM_CHANNEL_BYTES = 3
- private const val NUM_PANID_BYTES = 2
- private const val NUM_XPANID_BYTES = 8
- private const val NUM_MASTER_KEY_BYTES = 16
- private const val TYPE_CHANNEL = 0 // Type of Thread Channel TLV.
- private const val TYPE_PANID = 1 // Type of Thread PAN ID TLV.
- private const val TYPE_XPANID = 2 // Type of Thread Extended PAN ID TLV.
- private const val TYPE_MASTER_KEY = 5 // Type of Thread Network Master Key TLV.
- public const val MATTER_DEVICE_LOCK = "MATTER-3840"
- public const val MATTER_DEVICE_LIGHT = "Silabs-Light"
- public const val MATTER_DEVICE_WINDOW = "Silabs-Window"
- public const val MATTER_DEVICE_SENSOR = "SL-SENSOR"
- private const val STATUS_PAIRING_SUCCESS = 0
- private const val DEVICE_ATTESTATION_FAILED_TIMEOUT = 600
- public const val ON_OFF_CLUSTER_ENDPOINT = 1
- private const val COLON_WITH_SPACE = " - "
- public const val SPACE = " "
- private const val DIALOG_THREAD_FRAGMENT = 999
- private const val DIALOG_WIFI_FRAGMENT = 998
- const val DIA_INPUT_NTW_TYPE = "dia_input_ntw_type"
- const val DIALOG_OTBR_INFO = "Dialog_OTBR_Info"
- private const val DIALOG_THREAD_INPUT_TAG = "MatterThreadDialogFragmentTAG"
- private const val DIALOG_WIFI_INPUT_TAG = "MatterWiFiDialogFragmentTAG"
- fun newInstance(): MatterConnectFragment {
- val args = Bundle()
-
- val fragment = MatterConnectFragment()
- fragment.arguments = args
- return fragment
- }
- }
-
-}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterContactSensorFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterContactSensorFragment.kt
index bbd51868..42b9bd4a 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterContactSensorFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterContactSensorFragment.kt
@@ -1,11 +1,9 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.fragments
-import android.content.Context
import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -34,15 +32,12 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFrag
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.jetbrains.annotations.NotNull
import timber.log.Timber
-import kotlin.Exception
class MatterContactSensorFragment : Fragment() {
@@ -64,29 +59,25 @@ class MatterContactSensorFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mPrefs = requireContext().getSharedPreferences(
- "your_preference_name",
+ MatterDemoActivity.MATTER_PREF,
AppCompatActivity.MODE_PRIVATE
)
if (requireArguments() != null) {
model = requireArguments().getParcelable(ARG_DEVICE_MODEL)!!
deviceId = model.deviceId
- Timber.tag(TAG).e( "deviceID: " + model)
+ Timber.tag(TAG).e("deviceID: $model")
}
if (deviceId != null) {
+ showMatterProgressDialog(getString(R.string.matter_device_status))
- showMatterProgressDialog(getString(R.string.please_wait))
-
- // retrieveSavedDevices()
- GlobalScope.launch {
+ CoroutineScope(Dispatchers.IO).launch {
// This code will run asynchronously
- val resultq = checkForDeviceStatus()
- if (resultq) {
+ val resultInfo = checkForDeviceStatus()
+ if (resultInfo) {
println("Operation was successful")
removeProgress()
- // prepareList()
-
}
}
}
@@ -96,7 +87,7 @@ class MatterContactSensorFragment : Fragment() {
}
private fun removeProgress() {
- if (customProgressDialog?.isShowing() == true) {
+ if (customProgressDialog?.isShowing == true) {
customProgressDialog?.dismiss()
}
}
@@ -110,7 +101,7 @@ class MatterContactSensorFragment : Fragment() {
override fun onDeviceConnected(devicePointer: Long) {
model.isDeviceOnline = true
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
- removeProgress()
+ removeProgress()
}
@@ -136,13 +127,14 @@ class MatterContactSensorFragment : Fragment() {
customProgressDialog = CustomProgressDialog(requireContext())
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.show()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
binding = FragmentMatterContactSensorBinding.inflate(inflater, container, false)
return binding.root
@@ -159,19 +151,17 @@ class MatterContactSensorFragment : Fragment() {
}
- fun startUpdates() {
+ private fun startUpdates() {
stopUpdates()
job = scopeFun.launch {
while (true) {
- // getData() // the function that should be ran every second
- // sendReadValueCommandClick()
sendReadValue()
delay(2000)
}
}
}
- fun stopUpdates() {
+ private fun stopUpdates() {
job?.cancel()
job = null
}
@@ -204,7 +194,6 @@ class MatterContactSensorFragment : Fragment() {
getContactSensorClusterForDevice().readStateValueAttribute(
object : ChipClusters.BooleanAttributeCallback {
override fun onSuccess(value: Boolean) {
- // removeProgress()
println("Contact Value : $value")
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
requireActivity().runOnUiThread {
@@ -219,11 +208,10 @@ class MatterContactSensorFragment : Fragment() {
}
override fun onError(error: Exception?) {
- // removeProgress()
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
showMessageDialog()
- Timber.tag(TAG).e( "error readStateValueAttribute " + error)
+ Timber.tag(TAG).e("error readStateValueAttribute :$error")
}
}
@@ -237,24 +225,17 @@ class MatterContactSensorFragment : Fragment() {
}
}
- override fun onAttach(@NotNull context: Context) {
- super.onAttach(context)
- }
-
- override fun onDetach() {
- super.onDetach()
- }
private fun showMessageDialog() {
try {
- if (isAdded() && requireActivity() != null && !requireActivity().isFinishing) {
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
if (!MessageDialogFragment.isDialogShowing()) {
dialog = MessageDialogFragment()
dialog.setMessage(getString(R.string.matter_device_offline_text))
dialog.setOnDismissListener {
removeProgress()
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(
this@MatterContactSensorFragment,
@@ -272,33 +253,32 @@ class MatterContactSensorFragment : Fragment() {
} else {
Timber.e(TAG, "device offline")
}
- }catch (e:Exception){
- Timber.e(TAG,""+ e)
+ } catch (e: Exception) {
+ Timber.e(TAG, "Exception Occurred: $e")
}
-
}
inner class ContactSensorChipControllerCallback : GenericChipDeviceListener() {
override fun onConnectDeviceComplete() {}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
- Timber.tag(TAG).d( "onCommissioningComplete for nodeId $nodeId: $errorCode")
- // showMessage("Address update complete for nodeId $nodeId with code $errorCode")
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
+ Timber.tag(TAG).d("onCommissioningComplete for nodeId $nodeId: $errorCode")
+ // showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}
override fun onNotifyChipConnectionClosed() {
- Timber.tag(TAG).d( "onNotifyChipConnectionClosed")
+ Timber.tag(TAG).d("onNotifyChipConnectionClosed")
}
override fun onCloseBleComplete() {
- Timber.tag(TAG).d( "onCloseBleComplete")
+ Timber.tag(TAG).d("onCloseBleComplete")
}
- override fun onError(error: Throwable) {
+ override fun onError(error: Throwable?) {
super.onError(error)
- Timber.tag(TAG).d( "onError : $error")
+ Timber.tag(TAG).d("onError : $error")
}
}
@@ -307,7 +287,7 @@ class MatterContactSensorFragment : Fragment() {
}
companion object {
- private val TAG = MatterContactSensorFragment.javaClass.simpleName.toString()
+ private val TAG = Companion::class.java.simpleName.toString()
fun newInstance(): MatterContactSensorFragment = MatterContactSensorFragment()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterDishwasherFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterDishwasherFragment.kt
new file mode 100644
index 00000000..9851a85b
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterDishwasherFragment.kt
@@ -0,0 +1,1238 @@
+package com.siliconlabs.bledemo.features.demo.matter_demo.fragments
+
+import android.annotation.SuppressLint
+import android.content.SharedPreferences
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.text.Html
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.activity.OnBackPressedCallback
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.text.HtmlCompat
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentTransaction
+import androidx.lifecycle.lifecycleScope
+import chip.devicecontroller.ChipClusters
+import chip.devicecontroller.ChipClusters.ElectricalEnergyMeasurementCluster
+import chip.devicecontroller.ChipClusters.OperationalStateCluster
+import chip.devicecontroller.ChipClusters.DeviceEnergyManagementCluster
+import chip.devicecontroller.ChipDeviceController
+import chip.devicecontroller.ChipStructs
+import chip.devicecontroller.GetConnectedDeviceCallbackJni
+import com.google.gson.Gson
+import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.bluetooth.beacon_utils.eddystone.Constants.SCAN_TIMER
+import com.siliconlabs.bledemo.databinding.FragmentMatterDishwasherBinding
+import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoActivity
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.CallBackHandler
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ARG_DEVICE_MODEL
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.INIT
+import com.siliconlabs.bledemo.features.demo.matter_demo.model.DishWasherModel
+import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.FragmentUtils
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFragment
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils.ARG_ADDED_DEVICE_INFO_LIST
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import timber.log.Timber
+
+class MatterDishwasherFragment : Fragment() {
+ private var progress: Int = 0
+ private lateinit var dialog: MessageDialogFragment
+ private val dialogTag = "MessageDialog"
+ private val deviceController: ChipDeviceController
+ get() = ChipClient.getDeviceController(requireContext())
+ private lateinit var mPrefs: SharedPreferences
+
+ private lateinit var scope: CoroutineScope
+ lateinit var binding: FragmentMatterDishwasherBinding
+ private var deviceId: Long = INIT
+ private var endpointId: Int = DISHWASHER_OPT_ENDPOINT
+ private lateinit var model: MatterScannedResultModel
+ private var customProgressDialog: CustomProgressDialog? = null
+ private var timer: CountDownTimer? = null
+ private var timeLeftInMillis: Long = 600000 // 10 minutes in milliseconds
+ private var isTimerRunning = false
+ private var isPaused = false
+ private var currentTotalEnergy: Float = 0.000F
+ private var currentInCycleEnergy: Float = 0.000F
+ private var cycleCounter: Int? = 0
+ private var mCurrentCycleState: Boolean = true
+ var mInCurrentCycleGlobalState = 0.000F
+ private lateinit var dishwasherPref: SharedPreferences
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ mPrefs = requireContext().getSharedPreferences(
+ MatterDemoActivity.MATTER_PREF, AppCompatActivity.MODE_PRIVATE
+ )
+ dishwasherPref = requireContext().getSharedPreferences(
+ DISHWASHER_PREF, AppCompatActivity.MODE_PRIVATE
+ )
+ model = requireArguments().getParcelable(ARG_DEVICE_MODEL)!!
+ deviceId = model.deviceId
+ Timber.tag(TAG).e("deviceID: $model")
+
+ showMatterProgressDialog(getString(R.string.matter_device_status))
+ CoroutineScope(Dispatchers.IO).launch {
+ val resultInfo = checkForDeviceStatus()
+ withContext(Dispatchers.Main) {
+ if (resultInfo) {
+ println("Operation was successful")
+ removeProgress()
+ }
+ }
+ }
+ }
+
+ private suspend fun checkForDeviceStatus(): Boolean {
+ return withContext(Dispatchers.Default) {
+ // Simulate a time-consuming task
+
+ deviceController.getConnectedDevicePointer(
+ deviceId,
+ object : GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback {
+ override fun onDeviceConnected(devicePointer: Long) {
+ println("----DevicePointer:$devicePointer")
+ model.isDeviceOnline = true
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
+ }
+
+ override fun onConnectionFailure(nodeId: Long, error: java.lang.Exception?) {
+ model.isDeviceOnline = false
+ removeProgress()
+ println("----nodeId:$nodeId")
+ println("----error:${error!!.message}")
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
+ showMessageDialog()
+
+ }
+ })
+
+ delay(SCAN_TIMER * 1000)
+ true
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ super.onCreateView(inflater, container, savedInstanceState)
+ binding = FragmentMatterDishwasherBinding.inflate(inflater, container, false)
+ viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
+ binding.btnOn.isEnabled = true
+ binding.btnOff.isEnabled = false
+ binding.btnPause.isEnabled = false
+ requireActivity().runOnUiThread {
+ imageDishwasherOff()
+ }
+ }
+ return binding.root
+ }
+
+ private fun showMessageDialog() {
+
+ try {
+ if (isAdded && !requireActivity().isFinishing) {
+ requireActivity().runOnUiThread {
+ if (!MessageDialogFragment.isDialogShowing()) {
+ dialog = MessageDialogFragment()
+ dialog.setMessage(getString(R.string.matter_device_offline_text))
+ dialog.setOnDismissListener {
+ removeProgress()
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
+ } else {
+ FragmentUtils.getHost(
+ this@MatterDishwasherFragment, CallBackHandler::class.java
+ ).onBackHandler()
+ }
+ }
+ val transaction: FragmentTransaction =
+ requireActivity().supportFragmentManager.beginTransaction()
+
+ dialog.show(transaction, dialogTag)
+ }
+ }
+ } else {
+ Timber.e("device offline")
+ }
+ } catch (e: Exception) {
+ Timber.tag(TAG).e("device offline device offline ${e.message}")
+ }
+
+ }
+
+ private fun removeProgress() {
+ if (customProgressDialog?.isShowing == true) {
+ customProgressDialog?.dismiss()
+ }
+ }
+
+ private fun showMatterProgressDialog(message: String) {
+ customProgressDialog = CustomProgressDialog(requireContext())
+ customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
+ customProgressDialog!!.show()
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ scope = viewLifecycleOwner.lifecycleScope
+ updateCompletedCycleTextCounter()
+ binding.btnOn.text = requireContext().getString(R.string.matter_dishwasher_on)
+ binding.btnOff.text = requireContext().getString(R.string.matter_dishwasher_off)
+ binding.btnPause.text = requireContext().getString(R.string.matter_dishwasher_pause)
+ (activity as MatterDemoActivity).hideQRScanner()
+
+ binding.btnOn.setOnClickListener {
+ DishWasherModel.dishwasherCurrentRunningState = "Started"
+ SharedPrefsUtils.saveDishwasherAppliedCycleStates(dishwasherPref, "Started")
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${currentInCycleEnergy}${" kWh"} "
+
+ )
+ binding.btnOff.isEnabled = true
+ binding.btnPause.isEnabled = true
+ binding.btnOn.isEnabled = false
+ scope.launch {
+ turnOnDishwasher()
+ readEnergy()
+ startDishwasherTimer()
+ }
+ }
+ binding.btnOff.setOnClickListener {
+ currentInCycleEnergy = 0.000F
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${
+ 0.000f
+ }${" kWh"} "
+
+ )
+
+ SharedPrefsUtils.saveDishwasherInCurrentCycleEnergyConsumed(dishwasherPref, 0.000f)
+ DishWasherModel.dishwasherCurrentRunningState = "Stopped"
+ SharedPrefsUtils.saveDishwasherAppliedCycleStates(dishwasherPref, "Stopped")
+ cycleCounter = cycleCounter!! + 1
+ updateCompletedCycleTextCounter()
+ binding.btnOn.isEnabled = true
+ binding.btnOff.isEnabled = false
+ binding.btnPause.isEnabled = false
+ mCurrentCycleState = false
+ scope.launch {
+ //getEleDevMag().subscribeCumulativeEnergyImportedAttribute(null,0,0)
+ //forcefully read the Dishwasher Firmware again!
+ readEnergy()
+ turnOffDishwasher()
+ stopDishwasherTimer()
+ }
+ mInCurrentCycleGlobalState = 0.000F
+ cycleCounter?.let {
+ SharedPrefsUtils.saveDishwasherCompletedCycleCount(
+ dishwasherPref, it
+ )
+ }
+ }
+ binding.btnPause.setOnClickListener {
+ binding.btnOn.isEnabled = false
+ binding.btnOff.isEnabled = true
+ binding.btnPause.isEnabled = true
+ if (isPaused) {
+ //resume dishwasher operations
+ scope.launch {
+ resumeDishwasher()
+ resumeDishwasherTimer()
+ }
+
+ } else {
+ //pause dishwasher operations
+ scope.launch {
+ pauseDishwasher()
+ pauseDishwasherTimer()
+ }
+
+ }
+ isPaused = !isPaused
+ if (isPaused) {
+ DishWasherModel.dishwasherCurrentRunningState = "Paused"
+ SharedPrefsUtils.saveDishwasherAppliedCycleStates(dishwasherPref, "Paused")
+ } else {
+ DishWasherModel.dishwasherCurrentRunningState = "Resumed"
+ SharedPrefsUtils.saveDishwasherAppliedCycleStates(dishwasherPref, "Resumed")
+ }
+ }
+ updateCountDownTimerText()
+ binding.matterProgressBar.max = 100
+ binding.matterProgressBar.rotation = 180F
+ //back handling
+ requireActivity().onBackPressedDispatcher.addCallback(
+ requireActivity(), onBackPressedCallback
+ )
+ }
+
+
+ private fun showAlertDialogForOtherOperations() {
+ val dialog = AlertDialog.Builder(requireContext()).setTitle(getString(R.string.alert))
+ .setMessage(getString(R.string.matter_dishwasher_navigating_back))
+ .setPositiveButton("OK") { _, _ ->
+ // Explicitly pause and navigate back
+ binding.btnPause.performClick()
+ DishWasherModel.dishwasherCurrentRunningState = "Paused"
+ SharedPrefsUtils.saveDishwasherAppliedCycleStates(dishwasherPref, "Paused")
+ requireActivity().supportFragmentManager.popBackStack()
+ }.setNegativeButton("Cancel") { dialog, _ ->
+ dialog.dismiss()
+ }.create()
+
+ dialog.show()
+ }
+
+ private val onBackPressedCallback = object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ if (isAdded) {
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ handleDishwasherBackNavigationUI()
+ } else {
+ FragmentUtils.getHost(
+ this@MatterDishwasherFragment,
+ MatterLightFragment.CallBackHandler::class.java
+ ).onBackHandler()
+ }
+ }
+ }
+ }
+
+ fun handleDishwasherBackNavigationUI() {
+ IS_BACK_BUTTON_CLICKED = true
+ if (DishWasherModel.dishwasherCurrentRunningState == "Started" ||
+ DishWasherModel.dishwasherCurrentRunningState == "Resumed") {
+ showAlertDialogForOtherOperations()
+ } else {
+ requireActivity().supportFragmentManager.popBackStack()
+ }
+ }
+
+ fun showAlertDialogForPausedState() {
+ val dialog = AlertDialog.Builder(requireContext()).setTitle(getString(R.string.alert))
+ .setMessage(getString(R.string.matter_dishwasher_navigating_back))
+ .setPositiveButton("OK") { _, _ ->
+ // Navigate back without explicitly pausing
+ DishWasherModel.dishwasherCurrentRunningState = "Paused"
+ SharedPrefsUtils.saveDishwasherAppliedCycleStates(dishwasherPref, "Paused")
+ requireActivity().supportFragmentManager.popBackStack()
+ }.setNegativeButton("Cancel") { dialog, _ ->
+ dialog.dismiss()
+ }.create()
+
+ dialog.show()
+ }
+
+
+ private fun updateCompletedCycleTextCounter() {
+ val htmlString =
+ "${context?.getString(R.string.matter_completed_cycle)}${" "}$cycleCounter"
+ // Set the HTML string to the TextView
+ binding.tvCompletedCycleText.text = Html.fromHtml(htmlString, Html.FROM_HTML_MODE_LEGACY)
+ }
+
+ private fun resumeDishwasherTimer() {
+ isTimerRunning = true
+ timer = object : CountDownTimer(timeLeftInMillis, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+ timeLeftInMillis = millisUntilFinished
+ updateCountDownTimerText()
+ updateMatterProgressBar()
+ SharedPrefsUtils.saveDishwasherTimeLeftFormatted(dishwasherPref, timeLeftInMillis)
+ }
+
+ override fun onFinish() {
+ updateCompletedCycleTextCounter()
+ binding.btnOff.performClick()
+ SharedPrefsUtils.saveDishwasherTimeLeftFormatted(dishwasherPref, timeLeftInMillis)
+ }
+ }.start()
+ //isPaused = false
+ binding.btnPause.text = getString(R.string.matter_dishwasher_pause)
+
+ }
+
+ private suspend fun resumeDishwasher() {
+ getDishwasherClusterForDevice().resume(object :
+ OperationalStateCluster.OperationalCommandResponseCallback {
+ override fun onError(error: java.lang.Exception?) {
+ println("Error: ${error!!.message}")
+ }
+
+ override fun onSuccess(commandResponseState: ChipStructs.OperationalStateClusterErrorStateStruct?) {
+ if (isAdded) {
+ requireActivity().runOnUiThread {
+ imageDishwasherResume()
+ if (SharedPrefsUtils.getDishwasherAppliedCycleStates(dishwasherPref) == "Resumed") {
+ if (SharedPrefsUtils.getDishwasherCompletedCycleCount(dishwasherPref) <= 0) {
+ currentTotalEnergy =
+ SharedPrefsUtils.getDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref
+ )
+ } else {
+ /*currentInCycleEnergy =
+ SharedPrefsUtils.getDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref
+ )
+ println("ScccccjustDishwasherInResume $currentInCycleEnergy")*/
+ currentTotalEnergy =
+ SharedPrefsUtils.getDishwasherTotalEnergyConsumption(
+ dishwasherPref
+ )
+
+ }
+ scope.launch {
+ if (isAdded) {
+ scope.launch(Dispatchers.Main) {
+ progress =
+ SharedPrefsUtils.getDishwasherCompletedCycleProgressBar(
+ dishwasherPref
+ )
+ updateMatterProgressBar()
+ }
+ }
+
+ readEnergyWhenInPauseOrResumeState()
+
+ }
+ }
+
+ }
+ }
+
+ }
+ }, TIME_OUT)
+ }
+
+ private suspend fun readEnergyWhenInPauseOrResumeState() {
+ getEleDevMag().subscribeCumulativeEnergyImportedAttribute(object :
+ ElectricalEnergyMeasurementCluster.CumulativeEnergyImportedAttributeCallback {
+ override fun onError(error: java.lang.Exception?) {
+ if (error != null) {
+ println("Error :${error.message}")
+ Timber.tag(TAG).e("Error :${error.message}")
+ if (isAdded && !requireActivity().isFinishing) {
+ requireActivity().runOnUiThread {
+ Toast.makeText(
+ requireContext(),
+ "Error Occurred:${error.message}",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+
+
+ }
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun onSuccess(value: ChipStructs.ElectricalEnergyMeasurementClusterEnergyMeasurementStruct?) {
+ if (isAdded && !requireActivity().isFinishing) {
+ requireActivity().runOnUiThread {
+ val energyValue = value?.energy
+ if (null != energyValue) {
+ val str = (energyValue?.toDouble())?.div(1_000_000)
+ val formattedEnergyValue = String.format("%.3f", str)
+ if (formattedEnergyValue.isNotEmpty() || formattedEnergyValue.isNotBlank()) {
+
+ //currentTotalEnergy = formattedEnergyValue.toFloat()
+ var previousCycle =
+ SharedPrefsUtils.getDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref
+ )
+ currentTotalEnergy =
+ SharedPrefsUtils.getDishwasherTotalEnergyConsumption(
+ dishwasherPref
+ )
+ currentInCycleEnergy = (formattedEnergyValue.toFloat() - currentTotalEnergy)+previousCycle
+
+ //in current cycle
+ if (SharedPrefsUtils.getDishwasherCompletedCycleCount(dishwasherPref) <= 0) {
+ // when the completed cycle is zero that is during the first cycle, in current cycle
+ //will be the Total energy coming from the firmware
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${
+ String.format(
+ "%.3f", currentTotalEnergy
+ )
+ }${" kWh"} "
+
+ )
+ lifecycleScope.launch(Dispatchers.IO) {
+ SharedPrefsUtils.saveDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref,
+ String.format("%.3f", currentTotalEnergy).toFloat()
+ )
+ }
+
+ } else {
+ //lifecycleScope.launch {
+ //delay(60000)
+ if(!DishWasherModel.dishwasherCurrentRunningState.equals(
+ "Stopped", ignoreCase = true
+ )){
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${
+ String.format(
+ "%.3f", currentInCycleEnergy
+ )
+ }${" kWh"} "
+
+ )
+ // }
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ SharedPrefsUtils.saveDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref,
+ String.format("%.3f", currentInCycleEnergy).toFloat()
+ )
+ }
+ }
+
+ if(DishWasherModel.dishwasherCurrentRunningState.equals(
+ "Stopped", ignoreCase = true
+ )) {
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ }
+ }
+ // in Total
+ if (cycleCounter!! <= 0) {
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "$formattedEnergyValue${" kWh"} "
+
+ )
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ SharedPrefsUtils.saveDishwasherTotalEnergyConsumption(
+ dishwasherPref, formattedEnergyValue.toFloat()
+ )
+ }
+ } else {
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "$formattedEnergyValue${" kWh"} "
+
+ )
+
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${
+ String.format(
+ "%.3f", formattedEnergyValue.toFloat().div(cycleCounter!!)
+ )
+ }${" kWh"} "
+
+ )
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ SharedPrefsUtils.saveDishwasherTotalEnergyConsumption(
+ dishwasherPref, formattedEnergyValue.toFloat()
+ )
+ }
+ }
+
+ // average energy per cycle
+ val averageCurrentEnergyPerCycle =
+ formattedEnergyValue.toFloat().div(cycleCounter!!)
+ if (averageCurrentEnergyPerCycle.isInfinite()) {
+
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ }
+ if (cycleCounter!! <= 0) {
+
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${formattedEnergyValue}${" kWh"} "
+
+ )
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ SharedPrefsUtils.saveDishwasherAverageEnergyPerCycle(
+ dishwasherPref, formattedEnergyValue.toFloat()
+ )
+ }
+ } else {
+ /*if (DishWasherModel.dishwasherCurrentRunningState.equals(
+ "Stopped", ignoreCase = true
+ )
+ ) {*/
+
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${
+ String.format(
+ "%.3f", averageCurrentEnergyPerCycle
+ )
+ }${" kWh"} "
+
+ )
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ SharedPrefsUtils.saveDishwasherAverageEnergyPerCycle(
+ dishwasherPref,
+ String.format("%.3f", averageCurrentEnergyPerCycle)
+ .toFloat()
+ )
+ }
+ //}
+ }
+ } else {
+
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ }
+ } else {
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ }
+
+ }
+ }
+
+ }
+ }, 1, 2)
+ }
+
+
+ private fun imageDishwasherResume() {
+ if (isAdded) {
+ requireActivity().runOnUiThread {
+ binding.btnMatterDeviceState.setImageResource(R.drawable.dishwasher_state_on)
+ binding.btnMatterDeviceState.setColorFilter(
+ ContextCompat.getColor(requireContext(), R.color.silabs_dark_blue),
+ android.graphics.PorterDuff.Mode.SRC_IN
+ )
+ binding.txtClusterStatus.text = requireContext().getString(R.string.blinky_tb_on)
+ }
+ }
+ }
+
+ private fun updateCountDownTimerText() {
+ val minutes = (timeLeftInMillis / 1000) / 60
+ val seconds = (timeLeftInMillis / 1000) % 60
+
+ val timeLeftFormatted = String.format("%02d:%02d", minutes, seconds)
+ val htmlString =
+ "${context?.getString(R.string.matter_remaining_time)}${" "}$timeLeftFormatted ${
+ context?.getString(R.string.matter_min)
+ }"
+ // Set the HTML string to the TextView
+ binding.progressMatterText.text = Html.fromHtml(htmlString, Html.FROM_HTML_MODE_LEGACY)
+
+ }
+
+ private fun pauseDishwasherTimer() {
+ if (!isTimerRunning) return
+
+ timer?.cancel()
+ isTimerRunning = false
+ //isPaused = true
+ binding.btnPause.text = getString(R.string.matter_resume)
+ }
+
+ private fun stopDishwasherTimer() {
+ timer?.cancel()
+ timeLeftInMillis = 600000 // Reset to 10 minutes
+ updateCountDownTimerText()
+ binding.matterProgressBar.progress = 0
+ isTimerRunning = false
+ }
+
+ private fun startDishwasherTimer() {
+ if (isTimerRunning) return
+
+ timer = object : CountDownTimer(timeLeftInMillis, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+ timeLeftInMillis = millisUntilFinished
+ updateCountDownTimerText()
+ updateMatterProgressBar()
+ SharedPrefsUtils.saveDishwasherTimeLeftFormatted(dishwasherPref, timeLeftInMillis)
+ }
+
+ override fun onFinish() {
+ updateCompletedCycleTextCounter()
+ binding.btnOff.performClick()
+ SharedPrefsUtils.saveDishwasherTimeLeftFormatted(dishwasherPref, timeLeftInMillis)
+ }
+ }.start()
+
+ isTimerRunning = true
+ }
+
+ private fun updateMatterProgressBar() {
+ progress = ((600000 - timeLeftInMillis).toFloat() / 600000 * 100).toInt()
+ SharedPrefsUtils.saveDishwasherCompletedCycleProgressBar(dishwasherPref, progress)
+ binding.matterProgressBar.progress = progress.toInt()
+ }
+
+ private suspend fun getDishwasherDeviceEnergyManagement(): DeviceEnergyManagementCluster {
+ return DeviceEnergyManagementCluster(
+ ChipClient.getConnectedDevicePointer(requireContext(), deviceId),
+ DISHWASHER_DEVICE_ENERGY_MANAGEMENT_ENDPOINT
+ )
+ }
+
+ private suspend fun getEleDevMag(): ElectricalEnergyMeasurementCluster {
+ return ElectricalEnergyMeasurementCluster(
+ ChipClient.getConnectedDevicePointer(requireContext(), deviceId),
+ DISHWASHER_ELECTRICAL_POWER_MEASUREMENT_ENDPOINT
+ )
+ }
+
+ private suspend fun getDishwasherClusterForDevice(): OperationalStateCluster {
+ return OperationalStateCluster(
+ ChipClient.getConnectedDevicePointer(requireContext(), deviceId), endpointId
+ )
+
+ }
+
+ private suspend fun readEnergy() {
+ getEleDevMag().subscribeCumulativeEnergyImportedAttribute(object :
+ ElectricalEnergyMeasurementCluster.CumulativeEnergyImportedAttributeCallback {
+ override fun onError(error: java.lang.Exception?) {
+ if (error != null) {
+ println("Error :${error.message}")
+ Timber.tag(TAG).e("Error :${error.message}")
+ if (isAdded) {
+ requireActivity().runOnUiThread {
+ Toast.makeText(
+ requireContext(),
+ "Error Occurred:${error.message}",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+
+ }
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun onSuccess(value: ChipStructs.ElectricalEnergyMeasurementClusterEnergyMeasurementStruct?) {
+ if (isAdded) {
+ requireActivity().runOnUiThread {
+ val energyValue = value?.energy
+ if (null != energyValue) {
+ val str = (energyValue?.toDouble())?.div(1_000_000)
+ val formattedEnergyValue = String.format("%.3f", str)
+ if (formattedEnergyValue.isNotEmpty() || formattedEnergyValue.isNotBlank()) {
+ currentTotalEnergy = formattedEnergyValue.toFloat()
+ if (mInCurrentCycleGlobalState == 0.000F) {
+ mInCurrentCycleGlobalState = formattedEnergyValue.toFloat()
+ }
+ //currentInCycleEnergy = currentTotalEnergy - currentInCycleEnergy
+ if(cycleCounter!! <= 0){
+ currentInCycleEnergy =
+ currentTotalEnergy
+ }else{
+ currentInCycleEnergy =
+ currentTotalEnergy - mInCurrentCycleGlobalState
+ }
+
+ //in current cycle
+ if (mCurrentCycleState) {
+ mCurrentCycleState = false
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${"${String.format("%.3f", currentInCycleEnergy)}"}${" kWh"} "
+
+ )
+ } else {
+ if (cycleCounter!! <= 0) {
+ // when the completed cycle is zero that is during the first cycle, in current cycle
+ //will be the Total energy coming from the firmware
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${
+ String.format(
+ "%.3f", currentTotalEnergy
+ )
+ }${" kWh"} "
+
+ )
+ SharedPrefsUtils.saveDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref,
+ String.format("%.3f", currentTotalEnergy).toFloat()
+ )
+ } else {
+ //lifecycleScope.launch {
+ //delay(60000)
+ if(!DishWasherModel.dishwasherCurrentRunningState.equals(
+ "Stopped", ignoreCase = true
+ )) {
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${
+ String.format(
+ "%.3f", currentInCycleEnergy
+ )
+ }${" kWh"} "
+
+ )
+ //}
+ SharedPrefsUtils.saveDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref,
+ String.format("%.3f", currentInCycleEnergy).toFloat()
+ )
+ }
+
+ }
+ if(DishWasherModel.dishwasherCurrentRunningState.equals(
+ "Stopped", ignoreCase = true
+ )) {
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ }
+ }
+
+
+ // in Total
+ if (cycleCounter!! <= 0) {
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "$formattedEnergyValue${" kWh"} "
+
+ )
+ SharedPrefsUtils.saveDishwasherTotalEnergyConsumption(
+ dishwasherPref, formattedEnergyValue.toFloat()
+ )
+ } else {
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "$formattedEnergyValue${" kWh"} "
+
+ )
+ SharedPrefsUtils.saveDishwasherTotalEnergyConsumption(
+ dishwasherPref, formattedEnergyValue.toFloat()
+ )
+ }
+ // average energy per cycle
+ val averageCurrentEnergyPerCycle =
+ currentTotalEnergy.div(cycleCounter!!)
+ if (averageCurrentEnergyPerCycle.isInfinite()) {
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ }
+ if (cycleCounter!! <= 0) {
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${formattedEnergyValue}${" kWh"} "
+
+ )
+ SharedPrefsUtils.saveDishwasherAverageEnergyPerCycle(
+ dishwasherPref, formattedEnergyValue.toFloat()
+ )
+ } else {
+ /*if (DishWasherModel.dishwasherCurrentRunningState.equals(
+ "Stopped", ignoreCase = true
+ )
+ ) {*/
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${
+ String.format(
+ "%.3f", averageCurrentEnergyPerCycle
+ )
+ }${" kWh"} "
+
+ )
+ SharedPrefsUtils.saveDishwasherAverageEnergyPerCycle(
+ dishwasherPref,
+ String.format("%.3f", averageCurrentEnergyPerCycle)
+ .toFloat()
+ )
+ //}
+ }
+ } else {
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ }
+ } else {
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ }
+
+ }
+ }
+
+ }
+ }, 1, 10)
+ }
+
+ private suspend fun pauseDishwasher() {
+
+ getDishwasherClusterForDevice().pause(object :
+ OperationalStateCluster.OperationalCommandResponseCallback {
+ override fun onError(error: java.lang.Exception?) {
+ println("Error: ${error!!.message}")
+ }
+
+ override fun onSuccess(commandResponseState: ChipStructs.OperationalStateClusterErrorStateStruct?) {
+ imageDishwasherPause()
+ }
+ }, TIME_OUT)
+
+ }
+
+ private suspend fun turnOffDishwasher() {
+ getDishwasherClusterForDevice().stop(object :
+ OperationalStateCluster.OperationalCommandResponseCallback {
+ override fun onError(error: java.lang.Exception?) {
+ println("Error: ${error!!.message}")
+ }
+
+ override fun onSuccess(commandResponseState: ChipStructs.OperationalStateClusterErrorStateStruct?) {
+ imageDishwasherOff()
+ }
+
+ })
+
+ }
+
+ private suspend fun turnOnDishwasher() {
+ getDishwasherClusterForDevice().start(object :
+ OperationalStateCluster.OperationalCommandResponseCallback {
+ override fun onError(error: java.lang.Exception?) {
+ println("Error: ${error!!.message}")
+ }
+
+ override fun onSuccess(commandResponseState: ChipStructs.OperationalStateClusterErrorStateStruct?) {
+ imageDishwasherOn()
+ }
+
+ }, TIME_OUT)
+ }
+
+ private fun imageDishwasherPause() {
+ if (isAdded) {
+ requireActivity().runOnUiThread {
+ binding.btnMatterDeviceState.setImageResource(R.drawable.ic_dishwasher_icon_stateoff)
+ binding.btnMatterDeviceState.setColorFilter(
+ ContextCompat.getColor(requireContext(), R.color.silabs_dark_blue),
+ android.graphics.PorterDuff.Mode.SRC_IN
+ )
+ binding.txtClusterStatus.text =
+ requireContext().getString(R.string.matter_dishwasher_pause)
+ }
+ }
+ }
+
+ private fun imageDishwasherOff() {
+ if (isAdded) {
+ requireActivity().runOnUiThread {
+ binding.btnMatterDeviceState.setImageResource(R.drawable.ic_dishwasher_icon_stateoff)
+ binding.btnMatterDeviceState.setColorFilter(
+ ContextCompat.getColor(requireContext(), R.color.silabs_dark_gray_icon),
+ android.graphics.PorterDuff.Mode.SRC_IN
+ )
+ binding.txtClusterStatus.text = requireContext().getString(R.string.blinky_tb_off)
+ isPaused = false
+ binding.btnPause.text = getString(R.string.matter_dishwasher_pause)
+
+ }
+ }
+ }
+
+ private fun imageDishwasherOn() {
+ if (isAdded) {
+ requireActivity().runOnUiThread {
+ binding.btnMatterDeviceState.setImageResource(R.drawable.dishwasher_state_on)
+ binding.btnMatterDeviceState.setColorFilter(
+ ContextCompat.getColor(requireContext(), R.color.silabs_dark_blue),
+ android.graphics.PorterDuff.Mode.SRC_IN
+ )
+ binding.txtClusterStatus.text = requireContext().getString(R.string.blinky_tb_on)
+ }
+ }
+ }
+
+ interface CallBackHandler {
+ fun onBackHandler()
+ }
+
+ companion object {
+ private val TAG = Companion::class.java.simpleName.toString()
+ const val DISHWASHER_PREF = "DISHWASHER_PREF"
+ fun newInstance(): MatterDishwasherFragment = MatterDishwasherFragment()
+
+ const val DISHWASHER_OPT_ENDPOINT = 1
+ const val DISHWASHER_ELECTRICAL_POWER_MEASUREMENT_ENDPOINT = 2
+ const val DISHWASHER_DEVICE_ENERGY_MANAGEMENT_ENDPOINT = 3
+ private const val TIME_OUT = 900
+ var IS_BACK_BUTTON_CLICKED = false
+ }
+
+
+ override fun onResume() {
+ super.onResume()
+ if (IS_BACK_BUTTON_CLICKED) {
+ IS_BACK_BUTTON_CLICKED = false
+ scope.launch {
+ //whenever the dishwasher is in pause or resume state,Call the firmware again
+ //for throwing the reading again
+ readEnergyWhenInPauseOrResumeState()
+ }
+ try {
+ if (isAdded) {
+ scope.launch(Dispatchers.Main) {
+ if (-1 != SharedPrefsUtils.getDishwasherCompletedCycleCount(dishwasherPref)) {
+ cycleCounter =
+ SharedPrefsUtils.getDishwasherCompletedCycleCount(dishwasherPref)
+ updateCompletedCycleTextCounter()
+ }
+ }
+ when (SharedPrefsUtils.getDishwasherAppliedCycleStates(dishwasherPref)) {
+
+ "Started" -> {
+ dishwasherStartCycle()
+ }
+
+ "Stopped" -> {
+ dishwasherStopCycle()
+ }
+
+ "Resumed" -> {
+ dishwasherResumeCycle()
+ }
+
+ "Paused" -> {
+ dishwasherPauseCycle()
+
+ }
+
+ else -> {
+ scope.launch(Dispatchers.Main) {
+ binding.btnOn.isEnabled = true
+ binding.btnOff.isEnabled = false
+ binding.btnPause.isEnabled = false
+ requireActivity().runOnUiThread {
+ imageDishwasherOff()
+ }
+ }
+
+ }
+ }
+ }
+ } catch (e: Exception) {
+ println("MatterDishwasherFragment ${e.message}")
+ }
+ }
+ }
+
+ private fun restoreRemainingDishwasgerTime() {
+ val timeLeft = SharedPrefsUtils.getDishwasherTimeLeftFormatted(dishwasherPref)
+
+ if (timeLeft != 0L) {
+ timeLeftInMillis = timeLeft
+ updateCountDownTimerText()
+ }
+ }
+
+ private fun dishwasherPauseCycle() {
+ // Retrieve the time left value from SharedPreferences
+ scope.launch(Dispatchers.Main) {
+ binding.btnPause.text = getString(R.string.matter_resume)
+ binding.btnOn.isEnabled = false
+ binding.btnOff.isEnabled = true
+ binding.btnPause.isEnabled = true
+ restoreRemainingDishwasgerTime()
+ progress = SharedPrefsUtils.getDishwasherCompletedCycleProgressBar(dishwasherPref)
+ updateMatterProgressBar()
+ isPaused = true
+ imageDishwasherPause()
+
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherTotalEnergyConsumption(
+ dishwasherPref
+ )
+ }${" kWh"} "
+
+ )
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherAverageEnergyPerCycle(
+ dishwasherPref
+ )
+ }${" kWh"} "
+
+ )
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref
+ )
+ }${" kWh"} "
+
+ )
+ }
+
+ }
+
+ private fun dishwasherResumeCycle() {
+ // Retrieve the time left value from SharedPreferences
+ scope.launch(Dispatchers.Main) {
+ binding.btnPause.text = getString(R.string.matter_dishwasher_pause)
+ binding.btnOn.isEnabled = false
+ binding.btnOff.isEnabled = true
+ binding.btnPause.isEnabled = true
+ restoreRemainingDishwasgerTime()
+ isPaused = false
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherTotalEnergyConsumption(
+ dishwasherPref
+ )
+ }${" kWh"} "
+
+ )
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherAverageEnergyPerCycle(
+ dishwasherPref
+ )
+ }${" kWh"} "
+
+ )
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref
+ )
+ }${" kWh"} "
+
+ )
+ imageDishwasherResume()
+ }
+
+
+ }
+
+ private fun dishwasherStopCycle() {
+ scope.launch(Dispatchers.Main) {
+ isPaused = false
+ binding.btnOn.isEnabled = true
+ binding.btnOff.isEnabled = false
+ binding.btnPause.isEnabled = false
+ imageDishwasherOff()
+ stopDishwasherTimer()
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherTotalEnergyConsumption(
+ dishwasherPref
+ )
+ }${" kWh"} "
+
+ )
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherAverageEnergyPerCycle(
+ dishwasherPref
+ )
+ }${" kWh"} "
+
+ )
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${
+ SharedPrefsUtils.getDishwasherInCurrentCycleEnergyConsumed(
+ dishwasherPref
+ )
+ }${" kWh"} "
+ )
+ }
+
+ }
+
+ private fun dishwasherStartCycle() {
+ scope.launch(Dispatchers.Main) {
+ isPaused = false
+ binding.btnOff.isEnabled = true
+ binding.btnPause.isEnabled = true
+ binding.btnOn.isEnabled = false
+ binding.tvTotalEnergyConsumption.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvEnergyMeterReading.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ binding.tvCurrentCycleEnergyComp.text = Html.fromHtml(
+ "${"0.000"}${" kWh"} "
+
+ )
+ imageDishwasherOn()
+ }
+
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ if (timer != null) {
+ timer?.cancel()
+ }
+ if (scope != null) {
+ scope.cancel()
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterDoorFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterDoorFragment.kt
index e704fa38..6001239b 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterDoorFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterDoorFragment.kt
@@ -1,12 +1,10 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.fragments
import android.annotation.SuppressLint
-import android.content.Context
import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -36,12 +34,11 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFrag
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.jetbrains.annotations.NotNull
import timber.log.Timber
+import java.util.Optional
class MatterDoorFragment : Fragment() {
@@ -51,37 +48,35 @@ class MatterDoorFragment : Fragment() {
private val deviceController: ChipDeviceController
get() = ChipClient.getDeviceController(requireContext())
private lateinit var mPrefs: SharedPreferences
- private var scannedDeviceList = ArrayList()
+
private lateinit var scope: CoroutineScope
private lateinit var binding: FragmentMatterDoorLightBinding
private var deviceId: Long = INIT
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(
- "your_preference_name",
+ MatterDemoActivity.MATTER_PREF,
AppCompatActivity.MODE_PRIVATE
)
if (requireArguments() != null) {
model = requireArguments().getParcelable(ARG_DEVICE_MODEL)!!
deviceId = model.deviceId
- Timber.tag(TAG).e("deviceID: " + model)
+ Timber.tag(TAG).e("deviceID: $model")
}
if (deviceId != null) {
- showMatterProgressDialog(getString(R.string.please_wait))
- // retrieveSavedDevices()
- GlobalScope.launch {
+ showMatterProgressDialog(getString(R.string.matter_device_status))
+ CoroutineScope(Dispatchers.IO).launch {
// This code will run asynchronously
- val resultq = checkForDeviceStatus()
- if (resultq) {
+ val resulInfo = checkForDeviceStatus()
+ if (resulInfo) {
println("Operation was successful")
removeProgress()
- // prepareList()
-
}
}
}
@@ -124,6 +119,7 @@ class MatterDoorFragment : Fragment() {
private fun showMatterProgressDialog(message: String) {
customProgressDialog = CustomProgressDialog(requireContext())
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.setMessage(message)
customProgressDialog!!.show()
}
@@ -131,7 +127,7 @@ class MatterDoorFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
binding = FragmentMatterDoorLightBinding.inflate(inflater, container, false)
return binding.root
}
@@ -143,20 +139,21 @@ class MatterDoorFragment : Fragment() {
deviceController.setCompletionListener(DoorChipControllerCallback())
binding.btnMatterDeviceState.setImageResource(R.drawable.door_lock)
binding.txtClusterName.text = requireContext().getText(R.string.matter_door_title)
- binding.btnOn.setLongClickable(false);
- binding.btnOff.setLongClickable(false);
+ binding.btnOn.isLongClickable = false;
+ binding.btnOff.isLongClickable = false;
binding.btnOn.text = requireContext().getText(R.string.matter_locked_status)
binding.btnOff.text = requireContext().getText(R.string.matter_unlock_status)
binding.btnToggle.visibility = View.GONE
binding.btnOn.setOnClickListener {
+ showMatterProgressDialog(getString(R.string.matter_door_lock_in_progress))
scope.launch {
- // showMatterProgressDialog(getString(R.string.please_wait))
sendLockCommandClick()
}
}
binding.btnOff.setOnClickListener {
+ showMatterProgressDialog(getString(R.string.matter_door_lock_in_progress))
scope.launch {
sendUnlockCommandClick()
}
@@ -168,32 +165,23 @@ class MatterDoorFragment : Fragment() {
)
}
- override fun onAttach(@NotNull context: Context) {
- super.onAttach(context)
- }
-
- override fun onDetach() {
- super.onDetach()
- }
-
private fun showMessageDialog() {
try {
- if (isAdded && requireActivity() != null && !requireActivity().isFinishing) {
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
if (!MessageDialogFragment.isDialogShowing()) {
dialog = MessageDialogFragment()
dialog.setMessage(getString(R.string.matter_device_offline_text))
dialog.setOnDismissListener {
removeProgress()
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(
this@MatterDoorFragment,
CallBackHandler::class.java
- )
- .onBackHandler()
+ ).onBackHandler()
}
}
val transaction: FragmentTransaction =
@@ -206,14 +194,14 @@ class MatterDoorFragment : Fragment() {
Timber.e("device offline")
}
} catch (e: Exception) {
- Timber.e("device offline " + e)
+ Timber.e("device offline :$e")
}
}
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
requireActivity().supportFragmentManager.popBackStack();
} else {
FragmentUtils.getHost(this@MatterDoorFragment, CallBackHandler::class.java)
@@ -259,12 +247,11 @@ class MatterDoorFragment : Fragment() {
}
private suspend fun sendLockCommandClick() {
-
getLockUnlockClusterForDevice().lockDoor(
object : ChipClusters.DefaultClusterCallback {
override fun onSuccess() {
removeProgress()
- Timber.tag(TAG).e("lock command Success")
+ Timber.tag(TAG).e("Lock command Success")
binding.btnMatterDeviceState.setImageResource(R.drawable.door_lock)
}
@@ -272,18 +259,19 @@ class MatterDoorFragment : Fragment() {
removeProgress()
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
showMessageDialog()
-
}
- }, null,
+ }, Optional.empty(),
TIME_OUT
)
}
+
private suspend fun sendUnlockCommandClick() {
getLockUnlockClusterForDevice().unlockDoor(
object : ChipClusters.DefaultClusterCallback {
override fun onSuccess() {
+ removeProgress()
Timber.tag(TAG).e("Unlock command Success")
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
binding.btnMatterDeviceState.setImageResource(R.drawable.door_unlock)
@@ -291,12 +279,13 @@ class MatterDoorFragment : Fragment() {
@SuppressLint("TimberArgCount")
override fun onError(error: Exception?) {
+ removeProgress()
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
Timber.tag(TAG).e("Unlock command failure: $error")
showMessageDialog()
}
- }, null,
+ }, Optional.empty(),
TIME_OUT
)
}
@@ -311,7 +300,7 @@ class MatterDoorFragment : Fragment() {
inner class DoorChipControllerCallback : GenericChipDeviceListener() {
override fun onConnectDeviceComplete() {}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
Timber.tag(TAG).d("onCommissioningComplete for nodeId $nodeId: $errorCode")
// showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}
@@ -324,7 +313,7 @@ class MatterDoorFragment : Fragment() {
Timber.tag(TAG).d("onCloseBleComplete")
}
- override fun onError(error: Throwable) {
+ override fun onError(error: Throwable?) {
super.onError(error)
Timber.tag(TAG).d("onError : $error")
}
@@ -335,7 +324,7 @@ class MatterDoorFragment : Fragment() {
}
companion object {
- private val TAG = MatterDoorFragment.javaClass.simpleName.toString()
+ private val TAG = Companion::class.java.simpleName.toString()
fun newInstance(): MatterDoorFragment = MatterDoorFragment()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterLightFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterLightFragment.kt
index c7149797..874bf9f4 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterLightFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterLightFragment.kt
@@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
@@ -22,8 +21,6 @@ import com.siliconlabs.bledemo.bluetooth.beacon_utils.eddystone.Constants
import com.siliconlabs.bledemo.databinding.FragmentMatterDoorLightBinding
import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoActivity
import com.siliconlabs.bledemo.features.demo.matter_demo.controller.GenericChipDeviceListener
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterTemperatureSensorFragment.Companion.MAX_REFRESH_PERIOD_S
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterTemperatureSensorFragment.Companion.MIN_REFRESH_PERIOD_S
import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
@@ -32,7 +29,6 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFrag
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -55,21 +51,22 @@ class MatterLightFragment : Fragment() {
private var currLightStatus: Boolean = false
private lateinit var matterLightFragmentJob: Job
private val matterLightFragmentScope = CoroutineScope(Dispatchers.Main)
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- mPrefs = requireContext().getSharedPreferences("your_preference_name", Context.MODE_PRIVATE)
+ mPrefs = requireContext().getSharedPreferences(
+ MatterDemoActivity.MATTER_PREF,
+ Context.MODE_PRIVATE
+ )
model = requireArguments().getParcelable(ARG_DEVICE_MODEL)!!
deviceId = model.deviceId
Timber.tag(TAG).d("deviceID: $model")
- showMatterProgressDialog(getString(R.string.please_wait))
+ showMatterProgressDialog(getString(R.string.matter_device_status))
// retrieveSavedDevices()
- GlobalScope.launch {
+ CoroutineScope(Dispatchers.IO).launch {
// This code will run asynchronously
-
val results = checkForDeviceStatus()
if (results) {
println("Operation was successful")
@@ -101,28 +98,6 @@ class MatterLightFragment : Fragment() {
})
delay(Constants.SCAN_TIMER * 500)
-// if (model.isDeviceOnline) {
-// getOnOffClusterForDevice().subscribeOnOffAttribute(object :
-// ChipClusters.BooleanAttributeCallback {
-// override fun onSuccess(value: Boolean) {
-// println("subscribeOnOffAttribute $value")
-// Timber.tag(TAG).e("subscribeOnOffAttribute $value")
-// currLightStatus = value
-// if (currLightStatus) {
-// imageForLightOn()
-// } else {
-// imageForLightOff()
-// }
-// }
-//
-// override fun onError(error: java.lang.Exception?) {
-// Timber.tag(TAG).e("subscribeOnOffAttribute onError:$error")
-// }
-//
-// }, MIN_REFRESH_PERIOD_S, MAX_REFRESH_PERIOD_S)
-// }
-
- // Return the result (true or false based on the actual result)
true
}
}
@@ -140,7 +115,7 @@ class MatterLightFragment : Fragment() {
dialog.setOnDismissListener {
removeProgress()
if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(
this@MatterLightFragment, CallBackHandler::class.java
@@ -149,18 +124,15 @@ class MatterLightFragment : Fragment() {
}
val transaction: FragmentTransaction =
requireActivity().supportFragmentManager.beginTransaction()
-
dialog.show(transaction, dialogTag)
}
-
-
}
} else {
Timber.tag(TAG).e("device offline")
}
} catch (e: Exception) {
- Timber.e("" + e)
+ Timber.e("Exception Occurred $e")
}
@@ -176,13 +148,14 @@ class MatterLightFragment : Fragment() {
customProgressDialog = CustomProgressDialog(requireContext())
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.show()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
- ): View? {
+ ): View {
binding = FragmentMatterDoorLightBinding.inflate(inflater, container, false)
return binding.root
}
@@ -192,27 +165,24 @@ class MatterLightFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
scope = viewLifecycleOwner.lifecycleScope
deviceController.setCompletionListener(LightChipControllerCallback())
- imageForLightOff()
- binding.btnOn.setLongClickable(false);
- binding.btnOff.setLongClickable(false);
+ startBackgroundTask()
+ binding.btnOn.isLongClickable = false
+ binding.btnOff.isLongClickable = false
binding.btnOff.text = requireContext().getText(R.string.matter_light_off_status)
binding.btnOn.text = requireContext().getText(R.string.matter_light_on_status)
binding.btnToggle.text = requireContext().getText(R.string.matter_light_toggle_status)
binding.btnOn.setOnClickListener {
scope.launch {
- //showMatterProgressDialog(getString(R.string.please_wait))
sendOnCommandClick()
}
}
binding.btnOff.setOnClickListener {
- // showMatterProgressDialog(getString(R.string.please_wait))
scope.launch { sendOffCommandClick() }
}
binding.btnToggle.setOnClickListener {
- // showMatterProgressDialog(getString(R.string.please_wait))
scope.launch { sendToggleCommandClicked() }
}
(activity as MatterDemoActivity).hideQRScanner()
@@ -227,15 +197,13 @@ class MatterLightFragment : Fragment() {
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (isAdded) {
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(this@MatterLightFragment, CallBackHandler::class.java)
.onBackHandler()
}
}
-
-
}
}
@@ -258,7 +226,7 @@ class MatterLightFragment : Fragment() {
showMessageDialog()
}
- })
+ }, TIME_OUT)
}
private suspend fun sendOffCommandClick() {
@@ -296,7 +264,7 @@ class MatterLightFragment : Fragment() {
}
private fun imageForLightOff() {
- if (requireArguments() != null && isAdded) {
+ if (isAdded) {
requireActivity().runOnUiThread {
binding.btnMatterDeviceState.setImageResource(R.drawable.matter_light)
binding.btnMatterDeviceState.setColorFilter(
@@ -309,7 +277,7 @@ class MatterLightFragment : Fragment() {
}
private fun imageForLightOn() {
- if (requireArguments() != null && isAdded) {
+ if (isAdded) {
requireActivity().runOnUiThread {
binding.btnMatterDeviceState.setImageResource(R.drawable.matter_light)
binding.btnMatterDeviceState.setColorFilter(
@@ -321,17 +289,11 @@ class MatterLightFragment : Fragment() {
}
}
- private fun showMessage(msg: String) {
- requireActivity().runOnUiThread {
- Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
- }
- }
-
inner class LightChipControllerCallback : GenericChipDeviceListener() {
override fun onConnectDeviceComplete() {}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
Timber.tag(TAG).d("onCommissioningComplete for nodeId $nodeId: $errorCode")
// showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}
@@ -344,7 +306,7 @@ class MatterLightFragment : Fragment() {
Timber.tag(TAG).d("onCloseBleComplete")
}
- override fun onError(error: Throwable) {
+ override fun onError(error: Throwable?) {
super.onError(error)
println("MatterLight OnError: $error")
Timber.tag(TAG).e("OnError: $error")
@@ -360,11 +322,12 @@ class MatterLightFragment : Fragment() {
matterLightFragmentJob = matterLightFragmentScope.launch(Dispatchers.IO) {
while (true) {
delay(1000)
- getOnOffClusterForDevice().readOnOffAttribute(object : ChipClusters.BooleanAttributeCallback{
+ getOnOffClusterForDevice().readOnOffAttribute(object :
+ ChipClusters.BooleanAttributeCallback {
override fun onSuccess(value: Boolean) {
- if (value){
+ if (value) {
imageForLightOn()
- }else{
+ } else {
imageForLightOff()
}
}
@@ -376,12 +339,14 @@ class MatterLightFragment : Fragment() {
}
}
}
+
private fun stopBackgroundTask() {
if (::matterLightFragmentJob.isInitialized && matterLightFragmentJob.isActive) {
matterLightFragmentJob.cancel()
println("Background task stopped")
}
}
+
override fun onDestroyView() {
super.onDestroyView()
stopBackgroundTask()
@@ -390,12 +355,12 @@ class MatterLightFragment : Fragment() {
companion object {
private const val TAG = "MatterLightFragment"
- public const val ON_OFF_CLUSTER_ENDPOINT = 1
- public const val LEVEL_CONTROL_CLUSTER_ENDPOINT = 1
- public const val ARG_DEVICE_MODEL = "device_model"
- public const val ARG_DEVICE_INFO = "device_info"
- public const val TIME_OUT = 500
- public const val INIT = 0L
+ const val ON_OFF_CLUSTER_ENDPOINT = 1
+
+ const val ARG_DEVICE_MODEL = "device_model"
+ const val ARG_DEVICE_INFO = "device_info"
+ const val TIME_OUT = 900
+ const val INIT = 0L
fun newInstance(): MatterLightFragment = MatterLightFragment()
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterNetworkSelectionInputDialogFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterNetworkSelectionInputDialogFragment.kt
index 214341f9..b1caa4b9 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterNetworkSelectionInputDialogFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterNetworkSelectionInputDialogFragment.kt
@@ -34,12 +34,13 @@ class MatterNetworkSelectionInputDialogFragment : DialogFragment() {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
binding = DialogNetworkSelectionMatterBinding.inflate(inflater, container, false)
if (dialog != null && dialog!!.window != null) {
dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
dialog!!.window!!.requestFeature(Window.FEATURE_NO_TITLE);
+ dialog!!.setCanceledOnTouchOutside(false)
}
return binding.root
}
@@ -102,10 +103,6 @@ class MatterNetworkSelectionInputDialogFragment : DialogFragment() {
}
}
- fun stopDisplay() {
- dismiss()
- }
-
private fun getScreenWidth(activity: Activity): Int {
val size = Point()
activity.windowManager.defaultDisplay.getSize(size)
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterOTBRInputDialogFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterOTBRInputDialogFragment.kt
index 1b96a57d..ecb3b734 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterOTBRInputDialogFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterOTBRInputDialogFragment.kt
@@ -11,17 +11,16 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
-import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import com.siliconlabs.bledemo.databinding.FragmentOtbrInputDialogBinding
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterConnectFragment.Companion.DIALOG_OTBR_INFO
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannerFragment.Companion.DIALOG_OTBR_INFO
class MatterOTBRInputDialogFragment : DialogFragment() {
private lateinit var binding: FragmentOtbrInputDialogBinding
companion object {
- public const val WINDOW_SIZE = 0.65
+ const val WINDOW_SIZE = 0.65
fun newInstance(): MatterOTBRInputDialogFragment = MatterOTBRInputDialogFragment()
}
@@ -29,12 +28,13 @@ class MatterOTBRInputDialogFragment : DialogFragment() {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
binding = FragmentOtbrInputDialogBinding.inflate(inflater, container, false)
if (dialog != null && dialog!!.window != null) {
dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog!!.window!!.requestFeature(Window.FEATURE_NO_TITLE);
+ dialog!!.setCanceledOnTouchOutside(false)
}
return binding.root
}
@@ -74,19 +74,10 @@ class MatterOTBRInputDialogFragment : DialogFragment() {
}
}
- fun stopDisplay() {
- dismiss()
- }
private fun getScreenWidth(activity: Activity): Int {
val size = Point()
activity.windowManager.defaultDisplay.getSize(size)
return size.x
}
-
- override fun onDestroy() {
- super.onDestroy()
- }
-
-
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterOccupancySensorFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterOccupancySensorFragment.kt
index 15850302..6a9466b9 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterOccupancySensorFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterOccupancySensorFragment.kt
@@ -5,7 +5,6 @@ import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -21,14 +20,11 @@ import chip.devicecontroller.GetConnectedDeviceCallbackJni
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.bluetooth.beacon_utils.eddystone.Constants
import com.siliconlabs.bledemo.databinding.FragmentMatterOccupancySensorBinding
-import com.siliconlabs.bledemo.databinding.FragmentMatterThermostatBinding
import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoActivity
import com.siliconlabs.bledemo.features.demo.matter_demo.controller.GenericChipDeviceListener
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ARG_DEVICE_INFO
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ARG_DEVICE_MODEL
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.INIT
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ON_OFF_CLUSTER_ENDPOINT
-import com.siliconlabs.bledemo.features.demo.matter_demo.model.CHIPDeviceInfo
import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
@@ -45,8 +41,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jetbrains.annotations.NotNull
import timber.log.Timber
-import java.text.DecimalFormat
-import kotlin.Exception
class MatterOccupancySensorFragment : Fragment() {
@@ -66,7 +60,7 @@ class MatterOccupancySensorFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mPrefs = requireContext().getSharedPreferences(
- "your_preference_name",
+ MatterDemoActivity.MATTER_PREF,
AppCompatActivity.MODE_PRIVATE
)
if (requireArguments() != null) {
@@ -80,7 +74,7 @@ class MatterOccupancySensorFragment : Fragment() {
showMatterProgressDialog(getString(R.string.matter_device_status))
// retrieveSavedDevices()
- GlobalScope.launch {
+ CoroutineScope(Dispatchers.IO).launch {
// This code will run asynchronously
val resultq = checkForDeviceStatus()
@@ -107,7 +101,6 @@ class MatterOccupancySensorFragment : Fragment() {
model.isDeviceOnline = true
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
// removeProgress()
-
}
override fun onConnectionFailure(nodeId: Long, error: Exception?) {
@@ -124,17 +117,9 @@ class MatterOccupancySensorFragment : Fragment() {
}
}
- override fun onAttach(@NotNull context: Context) {
- super.onAttach(context)
- }
-
- override fun onDetach() {
- super.onDetach()
- }
-
private fun showMessageDialog() {
try {
- if (isAdded() && requireActivity() != null && !requireActivity().isFinishing) {
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
if (!MessageDialogFragment.isDialogShowing()) {
dialog = MessageDialogFragment()
@@ -161,14 +146,14 @@ class MatterOccupancySensorFragment : Fragment() {
Timber.e("device offline")
}
} catch (e: Exception) {
- Timber.e("" + e)
+ Timber.e("Exception Occurred :$e")
}
}
private fun removeProgress() {
- if (customProgressDialog?.isShowing() == true) {
+ if (customProgressDialog?.isShowing == true) {
customProgressDialog?.dismiss()
}
}
@@ -177,13 +162,14 @@ class MatterOccupancySensorFragment : Fragment() {
customProgressDialog = CustomProgressDialog(requireContext())
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.show()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
binding = FragmentMatterOccupancySensorBinding.inflate(inflater, container, false)
return binding.root
@@ -263,7 +249,7 @@ class MatterOccupancySensorFragment : Fragment() {
override fun onError(error: Exception?) {
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
- Timber.tag(TAG).e( "error readOccupancySensorType " + error)
+ Timber.tag(TAG).e( "error readOccupancySensorType :$error" )
showMessageDialog()
}
})
@@ -286,7 +272,7 @@ class MatterOccupancySensorFragment : Fragment() {
inner class OccupancySensorChipControllerCallback : GenericChipDeviceListener() {
override fun onConnectDeviceComplete() {}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
Timber.tag(TAG).d( "onCommissioningComplete for nodeId $nodeId: $errorCode")
//showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}
@@ -299,7 +285,7 @@ class MatterOccupancySensorFragment : Fragment() {
Timber.tag(TAG).d( "onCloseBleComplete")
}
- override fun onError(error: Throwable) {
+ override fun onError(error: Throwable?) {
super.onError(error)
Timber.tag(TAG).d( "onError : $error")
}
@@ -310,7 +296,7 @@ class MatterOccupancySensorFragment : Fragment() {
}
companion object {
- private val TAG = MatterOccupancySensorFragment.javaClass.simpleName.toString()
+ private val TAG = Companion::class.java.simpleName.toString()
fun newInstance(): MatterOccupancySensorFragment = MatterOccupancySensorFragment()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterPlugFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterPlugFragment.kt
index cc454c32..19fe710c 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterPlugFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterPlugFragment.kt
@@ -1,11 +1,10 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.fragments
-import android.content.Context
+import android.annotation.SuppressLint
import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -33,11 +32,9 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFrag
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.jetbrains.annotations.NotNull
import timber.log.Timber
@@ -58,24 +55,24 @@ class MatterPlugFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mPrefs = requireContext().getSharedPreferences(
- "your_preference_name",
+ MatterDemoActivity.MATTER_PREF,
AppCompatActivity.MODE_PRIVATE
)
if (requireArguments() != null) {
model = requireArguments().getParcelable(ARG_DEVICE_MODEL)!!
deviceId = model.deviceId
- Timber.tag(TAG).e( "deviceID: " + model)
+ Timber.tag(TAG).e("deviceID: $model")
}
if (deviceId != null) {
- showMatterProgressDialog(getString(R.string.please_wait))
+ showMatterProgressDialog(getString(R.string.matter_device_status))
// retrieveSavedDevices()
- GlobalScope.launch {
+ CoroutineScope(Dispatchers.IO).launch {
// This code will run asynchronously
- val resultq = checkForDeviceStatus()
- if (resultq) {
+ val resultInfo = checkForDeviceStatus()
+ if (resultInfo) {
println("Operation was successful")
removeProgress()
}
@@ -86,7 +83,7 @@ class MatterPlugFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
binding = FragmentMatterPlugBinding.inflate(inflater, container, false)
return binding.root
}
@@ -107,13 +104,13 @@ class MatterPlugFragment : Fragment() {
removeProgress()
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
showMessageDialog()
- requireActivity().runOnUiThread(Runnable {
+ requireActivity().runOnUiThread {
binding.btnMatterDeviceState.setImageResource(R.drawable.matter_plug_off)
binding.btnMatterDeviceState.setColorFilter(
ContextCompat.getColor(requireContext(), R.color.silabs_grey),
android.graphics.PorterDuff.Mode.SRC_IN
)
- })
+ }
}
})
@@ -125,31 +122,22 @@ class MatterPlugFragment : Fragment() {
}
}
- override fun onAttach(@NotNull context: Context) {
- super.onAttach(context)
- }
-
- override fun onDetach() {
- super.onDetach()
- }
-
private fun showMessageDialog() {
try {
- if (isAdded() && requireActivity() != null && !requireActivity().isFinishing) {
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
if (!MessageDialogFragment.isDialogShowing()) {
dialog = MessageDialogFragment()
dialog.setMessage(getString(R.string.matter_device_offline_text))
dialog.setOnDismissListener {
removeProgress()
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(
this@MatterPlugFragment,
CallBackHandler::class.java
- )
- .onBackHandler()
+ ).onBackHandler()
}
}
val transaction: FragmentTransaction =
@@ -162,14 +150,14 @@ class MatterPlugFragment : Fragment() {
Timber.e("device offline")
}
} catch (e: Exception) {
- Timber.e("" + e)
+ Timber.e("Exception Occurred: $e")
}
}
private fun removeProgress() {
- if (customProgressDialog?.isShowing() == true) {
+ if (customProgressDialog?.isShowing == true) {
customProgressDialog?.dismiss()
}
}
@@ -178,6 +166,7 @@ class MatterPlugFragment : Fragment() {
customProgressDialog = CustomProgressDialog(requireContext())
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.show()
}
@@ -186,8 +175,8 @@ class MatterPlugFragment : Fragment() {
scope = viewLifecycleOwner.lifecycleScope
deviceController.setCompletionListener(LightChipControllerCallback())
binding.btnMatterDeviceState.setImageResource(R.drawable.matter_plug_off)
- binding.btnOn.setLongClickable(false);
- binding.btnOff.setLongClickable(false);
+ binding.btnOn.isLongClickable = false
+ binding.btnOff.isLongClickable = false
binding.btnOff.text = requireContext().getText(R.string.matter_light_off_status)
binding.btnOn.text = requireContext().getText(R.string.matter_light_on_status)
@@ -210,8 +199,8 @@ class MatterPlugFragment : Fragment() {
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(this@MatterPlugFragment, CallBackHandler::class.java)
.onBackHandler()
@@ -231,16 +220,17 @@ class MatterPlugFragment : Fragment() {
getPlugCluster().on(object : ChipClusters.DefaultClusterCallback {
override fun onSuccess() {
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
- requireActivity().runOnUiThread(Runnable {
+ requireActivity().runOnUiThread {
binding.btnMatterDeviceState.setImageResource(R.drawable.matter_plug_on)
- })
+ }
}
+ @SuppressLint("TimberArgCount")
override fun onError(ex: Exception) {
removeProgress()
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
- Timber.tag(TAG).e( "ON command failure", ex)
+ Timber.tag(TAG).e("ON command failure: $ex")
showMessageDialog()
}
@@ -251,16 +241,15 @@ class MatterPlugFragment : Fragment() {
getPlugCluster().off(object : ChipClusters.DefaultClusterCallback {
override fun onSuccess() {
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
- requireActivity().runOnUiThread(Runnable {
+ requireActivity().runOnUiThread {
binding.btnMatterDeviceState.setImageResource(R.drawable.matter_plug_off)
- })
-
+ }
}
override fun onError(ex: Exception) {
removeProgress()
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
- Timber.tag(TAG).e( "OFF command failure", ex)
+ Timber.tag(TAG).e("OFF command failure :$ex")
showMessageDialog()
}
})
@@ -281,22 +270,22 @@ class MatterPlugFragment : Fragment() {
inner class LightChipControllerCallback : GenericChipDeviceListener() {
override fun onConnectDeviceComplete() {}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
- Timber.tag(TAG).d( "onCommissioningComplete for nodeId $nodeId: $errorCode")
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
+ Timber.tag(TAG).d("onCommissioningComplete for nodeId $nodeId: $errorCode")
//showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}
override fun onNotifyChipConnectionClosed() {
- Timber.tag(TAG).d( "onNotifyChipConnectionClosed")
+ Timber.tag(TAG).d("onNotifyChipConnectionClosed")
}
override fun onCloseBleComplete() {
- Timber.tag(TAG).d( "onCloseBleComplete")
+ Timber.tag(TAG).d("onCloseBleComplete")
}
- override fun onError(error: Throwable) {
+ override fun onError(error: Throwable?) {
super.onError(error)
- Timber.tag(TAG).d( "onError: $error")
+ Timber.tag(TAG).d("onError: $error")
}
}
@@ -307,7 +296,7 @@ class MatterPlugFragment : Fragment() {
companion object {
private const val TAG = "MatterPlugFragment"
- public const val ARG_DEVICE_MODEL = "device_model"
+ const val ARG_DEVICE_MODEL = "device_model"
fun newInstance(): MatterPlugFragment = MatterPlugFragment()
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterScannedResultFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterScannedResultFragment.kt
index 42e6a8e9..17b4f473 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterScannedResultFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterScannedResultFragment.kt
@@ -39,9 +39,9 @@ class MatterScannedResultFragment : Fragment() {
private lateinit var scope: CoroutineScope
private lateinit var deviceList: ArrayList
private lateinit var binding: FragmentMatterScannedResultsBinding
- private var deviceId: Long = 0;
- private var deviceType: Int = 0;
- private var pos: Int = 0;
+ private var deviceId: Long = 0
+ private var deviceType: Int = 0
+ private var pos: Int = 0
private lateinit var matterAdapter: MatterScannedResultAdapter
private lateinit var mPrefs: SharedPreferences
@@ -57,7 +57,7 @@ class MatterScannedResultFragment : Fragment() {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
super.onCreateView(inflater, container, savedInstanceState)
scope = viewLifecycleOwner.lifecycleScope
binding = FragmentMatterScannedResultsBinding.inflate(inflater, container, false)
@@ -113,7 +113,10 @@ class MatterScannedResultFragment : Fragment() {
binding.tvQuickStartHyperlink.movementMethod = LinkMovementMethod.getInstance()
setListDisplay()
- requireActivity().onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
+ requireActivity().onBackPressedDispatcher.addCallback(
+ viewLifecycleOwner,
+ onBackPressedCallback
+ )
}
@@ -123,7 +126,7 @@ class MatterScannedResultFragment : Fragment() {
if (deviceList.size !== 0) {
Timber.tag(TAG).e("+ deviceList $deviceList")
matterAdapter = MatterScannedResultAdapter(deviceList)
- binding.recyclerViewScannedDevices.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
+ binding.recyclerViewScannedDevices.scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY
binding.recyclerViewScannedDevices.adapter = matterAdapter
binding.recyclerViewScannedDevices.addItemDecoration(
RecyclerViewMargin(resources.getDimensionPixelSize(R.dimen.matter_margin))
@@ -151,7 +154,6 @@ class MatterScannedResultFragment : Fragment() {
.setPositiveButton(ok, dialogClickListener)
.setNegativeButton(cancel, dialogClickListener).show()
}
-
})
} else {
binding.placeholder.visibility = View.VISIBLE
@@ -189,7 +191,7 @@ class MatterScannedResultFragment : Fragment() {
private fun navigateToDemos(model: MatterScannedResultModel) {
- deviceType = model.deviceType!!
+ deviceType = model.deviceType
when (deviceType) {
THERMOSTAT_TYPE -> {
@@ -200,7 +202,7 @@ class MatterScannedResultFragment : Fragment() {
).navigateToDemo(matterThermostatFragment, model)
}
- LIGHTNING_TYPE, ENHANCED_COLOR_LIGHT_TYPE, ONOFF_LIGHT_TYPE, TEMPERATURE_COLOR_LIGHT_TYPE -> {
+ DIMMABLE_LIGHT_TYPE, ENHANCED_COLOR_LIGHT_TYPE, ON_OFF_LIGHT_TYPE, COLOR_TEMPERATURE_LIGHT_TYPE -> {
val matterLightFragment = MatterLightFragment.newInstance()
FragmentUtils.getHost(
this@MatterScannedResultFragment,
@@ -208,7 +210,7 @@ class MatterScannedResultFragment : Fragment() {
).navigateToDemo(matterLightFragment, model)
}
- WINDOW_TYPE -> {
+ WINDOW_COVERING_TYPE -> {
val matterWindowCoverFragment = MatterWindowCoverFragment.newInstance()
FragmentUtils.getHost(
this@MatterScannedResultFragment,
@@ -216,7 +218,7 @@ class MatterScannedResultFragment : Fragment() {
).navigateToDemo(matterWindowCoverFragment, model)
}
- LOCK_TYPE -> {
+ DOOR_LOCK_TYPE -> {
val matterDoorFragment = MatterDoorFragment.newInstance()
FragmentUtils.getHost(
this@MatterScannedResultFragment,
@@ -248,15 +250,22 @@ class MatterScannedResultFragment : Fragment() {
).navigateToDemo(matterTemperatureSensorFragment, model)
}
- PLUG_TYPE -> {
+ DIMMABLE_PLUG_IN_UNIT_TYPE -> {
val matterPlugFragment = MatterPlugFragment.newInstance()
FragmentUtils.getHost(
this@MatterScannedResultFragment,
- Callback::
- class.java
+ Callback::class.java
).navigateToDemo(matterPlugFragment, model)
}
+ DISHWASHER_TYPE -> {
+ val matterDishwasherFragment = MatterDishwasherFragment.newInstance()
+ FragmentUtils.getHost(
+ this@MatterScannedResultFragment,
+ Callback::class.java
+ ).navigateToDemo(matterDishwasherFragment, model)
+ }
+
else -> {
println("Unhandled Operation....")
}
@@ -271,11 +280,6 @@ class MatterScannedResultFragment : Fragment() {
}
}
- override fun onDestroy() {
- super.onDestroy()
-
- }
-
interface Callback {
fun navigateToDemo(
@@ -289,18 +293,73 @@ class MatterScannedResultFragment : Fragment() {
private const val ARG_DEVICE_LIST = "device_list"
private const val TAG = "MatterScannedResultFragment"
private const val MATTER_URL = "https://docs.silabs.com/matter/2.1.0/matter-overview"
- public const val THERMOSTAT_TYPE = 769
- public const val LIGHTNING_TYPE = 257
- public const val WINDOW_TYPE = 514
- public const val LOCK_TYPE = 10
- public const val ENHANCED_COLOR_LIGHT_TYPE = 269
- public const val ONOFF_LIGHT_TYPE = 256
- public const val TEMPERATURE_COLOR_LIGHT_TYPE = 268
- // public const val SWITCH_TYPE = 259
- public const val OCCUPANCY_SENSOR_TYPE = 263
- public const val TEMPERATURE_SENSOR_TYPE = 770
- public const val CONTACT_SENSOR_TYPE = 21
- public const val PLUG_TYPE = 267
+
+
+ //Lighting Type
+ const val ON_OFF_LIGHT_TYPE = 256
+ const val DIMMABLE_LIGHT_TYPE = 257
+ const val COLOR_TEMPERATURE_LIGHT_TYPE = 268
+ const val ENHANCED_COLOR_LIGHT_TYPE = 269
+
+ //smart plugs/outlets and other actuators
+ const val ON_OFF_PLUG_IN_UNIT_TYPE = 266
+ const val DIMMABLE_PLUG_IN_UNIT_TYPE = 267
+ const val PUMP = 771
+
+ //switches and controls
+ const val ON_OFF_LIGHT_SWITCH = 259
+ const val DIMMER_SWITCH = 260
+ const val COLOR_DIMMER_SWITCH = 261
+ const val CONTROL_BRIDGE = 2112
+ const val PUMP_CONTROLLER = 772
+ const val GENERIC_SWITCH = 15
+
+ //sensors
+ const val CONTACT_SENSOR_TYPE = 21
+ const val LIGHT_SENSOR_TYPE = 262
+ const val OCCUPANCY_SENSOR_TYPE = 263
+ const val TEMPERATURE_SENSOR_TYPE = 770
+ const val PRESSURE_SENSOR_TYPE = 773
+ const val FLOW_SENSOR_TYPE = 774
+ const val HUMIDITY_SENSOR_TYPE = 775
+ const val ON_OFF_SENSOR_TYPE = 2128
+ const val SMOKE_CO_ALARM_TYPE = 118
+
+ //closures
+ const val DOOR_LOCK_TYPE = 10
+ const val DOOR_LOCK_CONTROLLER_TYPE = 11
+ const val WINDOW_COVERING_TYPE = 514
+ const val WINDOW_COVERING_CONTROLLER_TYPE = 515
+
+ //HVAC
+ const val HEATING_COOLING_UNIT_TYPE = 768
+ const val THERMOSTAT_TYPE = 769
+ const val FAN_TYPE = 43
+ const val AIR_PURIFIER_TYPE = 45
+ const val AIR_QUALITY_SENSOR_TYPE = 44
+
+ //media
+ const val BASIC_VIDEO_PLAYER_TYPE = 40
+ const val CASTING_VIDEO_PLAYER_TYPE = 35
+ const val SPEAKER_TYPE = 34
+ const val CONTENT_APP_TYPE = 36
+ const val CASTING_VIDEO_CLIENT_TYPE = 41
+ const val VIDEO_REMOTE_CONTROL_TYPE = 42
+
+ //Generic
+ const val MODE_SELECT_TYPE = 39
+
+ //robotic devices
+ const val ROBOTIC_VACUUM_CLEANER_TYPE = 116
+
+ //appliances
+ const val REFRIGERATOR_TYPE = 112
+ const val TEMPERATURE_CONTROLLED_CABINET_TYPE = 113
+ const val ROOM_AIR_CONDITIONER_TYPE =114
+ const val LAUNDRY_WASHER_TYPE = 115
+ const val DISHWASHER_TYPE = 117
+
+ //Hyperlink const
private const val HYPERLINK_START = 89
private const val HYPERLINK_END = 107
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 93c046fc..cc715023 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
@@ -2,9 +2,15 @@ package com.siliconlabs.bledemo.features.demo.matter_demo.fragments
import android.Manifest
import android.annotation.SuppressLint
-import android.bluetooth.BluetoothAdapter
+import android.app.Activity
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothGatt
+import android.content.DialogInterface
import android.content.Intent
+import android.content.SharedPreferences
import android.content.pm.PackageManager
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.os.Handler
@@ -16,6 +22,7 @@ import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity.MODE_PRIVATE
import androidx.camera.core.AspectRatio
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis
@@ -24,8 +31,13 @@ import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
-import chip.setuppayload.SetupPayload
+import androidx.lifecycle.lifecycleScope
+import chip.devicecontroller.ChipClusters
+import chip.devicecontroller.ChipDeviceController
+import chip.devicecontroller.ChipStructs
+import chip.devicecontroller.NetworkCredentials
import chip.setuppayload.SetupPayloadParser
import com.google.mlkit.vision.barcode.BarcodeScanner
import com.google.mlkit.vision.barcode.BarcodeScanning
@@ -34,11 +46,38 @@ import com.google.mlkit.vision.common.InputImage
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.databinding.FragmentMatterScannerBinding
import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoActivity
+import com.siliconlabs.bledemo.features.demo.matter_demo.controller.GenericChipDeviceListener
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ON_OFF_CLUSTER_ENDPOINT
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.CONTACT_SENSOR_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.DISHWASHER_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.ENHANCED_COLOR_LIGHT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.DIMMABLE_LIGHT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.DOOR_LOCK_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.OCCUPANCY_SENSOR_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.ON_OFF_LIGHT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.DIMMABLE_PLUG_IN_UNIT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.COLOR_TEMPERATURE_LIGHT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.TEMPERATURE_SENSOR_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.THERMOSTAT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.WINDOW_COVERING_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.manager.BluetoothManager
import com.siliconlabs.bledemo.features.demo.matter_demo.model.CHIPDeviceInfo
-import com.siliconlabs.bledemo.features.demo.matter_demo.model.ProvisionNetworkType
+import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
+import com.siliconlabs.bledemo.features.demo.matter_demo.model.NetworkCredentialsParcelable
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomInputDialog
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.DeviceIDUtil
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.FragmentUtils
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFragment
+import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
import com.siliconlabs.bledemo.features.iop_test.utils.DialogDeviceInfoFragment
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import matter.onboardingpayload.OnboardingPayload
+import matter.onboardingpayload.OnboardingPayloadParser
import timber.log.Timber
import java.util.concurrent.Executors
import kotlin.math.abs
@@ -47,22 +86,44 @@ import kotlin.math.min
class MatterScannerFragment : Fragment() {
- private lateinit var dialog: MessageDialogFragment
+
+ private var customProgressDialog: CustomProgressDialog? = null
val dialogTag = "MessageDialog"
- private lateinit var binding: FragmentMatterScannerBinding
- var networkSelectionDialog: MatterNetworkSelectionInputDialogFragment? = null
- private lateinit var networkMode: String
- private lateinit var payload: SetupPayload
+ private var networkSelectionDialog: MatterNetworkSelectionInputDialogFragment? = null
private var isShortDiscriminator = false
- private lateinit var qrCodeManualInput: String
private var deviceDialog: DialogDeviceInfoFragment? = null
- private var deviceInfodialogShown = false
+ private var deviceInfoDialogShown = false
+ private var otbrEntryDialog: MatterOTBRInputDialogFragment? = null
+ private var wifiEntryDialog: MatterWifiInputDialogFragment? = null
+ private var gatt: BluetoothGatt? = null
+ private var alertDialog: android.app.AlertDialog? = null
+ private var cameraProvider: ProcessCameraProvider? = null
+
+ private var deviceId: Long = 0
+ private lateinit var typeNtw: String
+ private lateinit var networkCredential: NetworkCredentialsParcelable
+ private lateinit var scope: CoroutineScope
+ private lateinit var bluetoothManager: BluetoothManager
+ private lateinit var networkMode: String
+ private lateinit var payload: OnboardingPayload
+ private lateinit var binding: FragmentMatterScannerBinding
+ private lateinit var dialog: MessageDialogFragment
+ private lateinit var matterScanDevice: BluetoothDevice
+ private lateinit var deviceInfo: CHIPDeviceInfo
+ private lateinit var deviceController: ChipDeviceController
+ private lateinit var qrCodeManualInput: String
+ private var scannedDeviceList = ArrayList()
+ private lateinit var mPrefs: SharedPreferences
+
@RequiresApi(Build.VERSION_CODES.S)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
-
+ deviceController = ChipClient.getDeviceController(requireContext())
+ mPrefs = requireContext().getSharedPreferences(
+ MatterDemoActivity.MATTER_PREF, MODE_PRIVATE
+ )
if (!hasLocationPermission()) {
requestLocationPermission()
}
@@ -70,16 +131,16 @@ class MatterScannerFragment : Fragment() {
if (!hasCameraPermission()) {
requestCameraPermission()
}
-
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MatterDemoActivity).showQRScanner()
+ scope = viewLifecycleOwner.lifecycleScope
binding.submitEntry.setOnClickListener {
qrCodeManualInput = binding.manualCodeEditText.text.toString().trim()
- println("Input MT : ${qrCodeManualInput}")
+ println("Input MT : $qrCodeManualInput")
handleManualInput(qrCodeManualInput)
}
}
@@ -91,10 +152,8 @@ class MatterScannerFragment : Fragment() {
}
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
super.onCreateView(inflater, container, savedInstanceState)
binding = FragmentMatterScannerBinding.inflate(inflater, container, false)
return binding.root
@@ -103,24 +162,20 @@ class MatterScannerFragment : Fragment() {
private fun startCamera() {
Timber.tag(TAG).e("startCamera")
val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
- cameraProviderFuture.addListener(Runnable {
- val cameraProvider = cameraProviderFuture.get()
+ cameraProviderFuture.addListener({
+ cameraProvider = cameraProviderFuture.get()
val metrics = DisplayMetrics().also { binding.cameraView.display?.getRealMetrics(it) }
val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)
if (binding.cameraView.display.rotation != null) {
- val preview: Preview = Preview.Builder()
- .setTargetAspectRatio(screenAspectRatio)
- .setTargetRotation(binding.cameraView.display.rotation)
- .build()
+ val preview: Preview = Preview.Builder().setTargetAspectRatio(screenAspectRatio)
+ .setTargetRotation(binding.cameraView.display.rotation).build()
preview.setSurfaceProvider(binding.cameraView.surfaceProvider)
// Setup barcode scanner
- val imageAnalysis = ImageAnalysis.Builder()
- .setTargetAspectRatio(screenAspectRatio)
- .setTargetRotation(binding.cameraView.display.rotation)
- .build()
+ val imageAnalysis = ImageAnalysis.Builder().setTargetAspectRatio(screenAspectRatio)
+ .setTargetRotation(binding.cameraView.display.rotation).build()
val cameraExecutor = Executors.newSingleThreadExecutor()
val barcodeScanner: BarcodeScanner = BarcodeScanning.getClient()
imageAnalysis.setAnalyzer(cameraExecutor) { imageProxy ->
@@ -128,8 +183,8 @@ class MatterScannerFragment : Fragment() {
}
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
- cameraProvider.unbindAll()
- cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis)
+ cameraProvider?.unbindAll()
+ cameraProvider?.bindToLifecycle(this, cameraSelector, preview, imageAnalysis)
} catch (exc: Exception) {
Timber.tag(TAG).e("Use case binding failed: $exc")
}
@@ -138,71 +193,73 @@ class MatterScannerFragment : Fragment() {
}, ContextCompat.getMainExecutor(requireContext()))
}
+ private fun stopCamera() {
+ cameraProvider?.unbindAll()
+ }
+
@SuppressLint("UnsafeOptInUsageError")
private fun processImageProxy(
- barcodeScanner: BarcodeScanner,
- imageProxy: ImageProxy
+ barcodeScanner: BarcodeScanner, imageProxy: ImageProxy
) {
val inputImage =
InputImage.fromMediaImage(imageProxy.image!!, imageProxy.imageInfo.rotationDegrees)
- barcodeScanner.process(inputImage)
- .addOnSuccessListener { barcode ->
- Timber.tag(TAG).e("Barcodes" + barcode)
- barcode.forEach {
- handleScannedQrCode(it)
- }
- }
- .addOnFailureListener {
- Timber.tag(TAG).e(it.message ?: it.toString())
- }
- .addOnCompleteListener {
- imageProxy.close()
+ barcodeScanner.process(inputImage).addOnSuccessListener { barcode ->
+ //Timber.tag(TAG).e("Barcodes: $barcode")
+ barcode.forEach {
+ handleScannedQrCode(it)
}
+ }.addOnFailureListener {
+ Timber.tag(TAG).e(it.message ?: it.toString())
+ }.addOnCompleteListener {
+ imageProxy.close()
+ }
}
private fun handleManualInput(qrCode: String) {
- if (qrCode.isNullOrBlank()) {
+ if (qrCode.isBlank()) {
showMessage(getString(R.string.matter_validation_manual_qrcode))
return
}
try {
- payload = SetupPayloadParser().parseQrCode(qrCode)
+ payload = if (qrCode.startsWith("MT:")) {
+ OnboardingPayloadParser().parseQrCode(qrCode)
+ } else {
+ OnboardingPayloadParser().parseManualPairingCode(qrCode)
+ }
println("Payload : $payload")
if (networkSelectionDialog == null) {
- val prev =
- requireActivity().supportFragmentManager.findFragmentByTag(
- ALERT_NTW_MODE_DIALOG_TAG
- )
+ val prev = requireActivity().supportFragmentManager.findFragmentByTag(
+ ALERT_NTW_MODE_DIALOG_TAG
+ )
if (prev == null) {
val chipDeviceInfo = """
- Version: ${payload.version ?: "N/A"}
+ Version: ${payload.version}
- Vendor ID: ${payload.vendorId ?: "N/A"}
+ Vendor ID: ${payload.vendorId}
- Product ID: ${payload.productId ?: "N/A"}
+ Product ID: ${payload.productId}
- Discriminator: ${payload.discriminator ?: "N/A"}
+ Discriminator: ${payload.discriminator}
- Setup PIN Code: ${payload.setupPinCode ?: "N/A"}
+ Setup PIN Code: ${payload.setupPinCode}
Discovery Capabilities: ${
- payload.discoveryCapabilities?.joinToString(", ") ?: "N/A"
+ payload.discoveryCapabilities.joinToString(", ")
}
- Commissioning Flow: ${payload.commissioningFlow ?: "N/A"}
+ Commissioning Flow: ${payload.commissioningFlow}
""".trimIndent()
showDeviceInfoDialog(chipDeviceInfo)
-
}
}
} catch (ex: SetupPayloadParser.SetupPayloadException) {
try {
- payload = SetupPayloadParser().parseManualEntryCode(qrCode)
+ payload = OnboardingPayloadParser().parseManualPairingCode(qrCode)
isShortDiscriminator = true
} catch (ex: Exception) {
Timber.tag(TAG).e("Unrecognized Manual Pairing Code $ex")
@@ -223,32 +280,32 @@ class MatterScannerFragment : Fragment() {
Handler(Looper.getMainLooper()).post {
try {
- payload = SetupPayloadParser().parseQrCode(barcode.displayValue)
+ payload = OnboardingPayloadParser().parseQrCode(barcode.displayValue!!)
+
isShortDiscriminator = true
if (networkSelectionDialog == null) {
- val prev =
- requireActivity().supportFragmentManager.findFragmentByTag(
- ALERT_NTW_MODE_DIALOG_TAG
- )
+ val prev = requireActivity().supportFragmentManager.findFragmentByTag(
+ ALERT_NTW_MODE_DIALOG_TAG
+ )
if (prev == null) {
val chipDeviceInfo = """
- Version: ${payload.version ?: "N/A"}
+ Version: ${payload.version}
- Vendor ID: ${payload.vendorId ?: "N/A"}
+ Vendor ID: ${payload.vendorId}
- Product ID: ${payload.productId ?: "N/A"}
+ Product ID: ${payload.productId}
- Discriminator: ${payload.discriminator ?: "N/A"}
+ Discriminator: ${payload.discriminator}
- Setup PIN Code: ${payload.setupPinCode ?: "N/A"}
+ Setup PIN Code: ${payload.setupPinCode}
Discovery Capabilities: ${
- payload.discoveryCapabilities?.joinToString(", ") ?: "N/A"
+ payload.discoveryCapabilities.joinToString(", ")
}
- Commissioning Flow: ${payload.commissioningFlow ?: "N/A"}
+ Commissioning Flow: ${payload.commissioningFlow}
""".trimIndent()
showDeviceInfoDialog(chipDeviceInfo)
@@ -274,7 +331,7 @@ class MatterScannerFragment : Fragment() {
private fun showMessageDialog(string: String) {
try {
- if (isAdded && requireActivity() != null && !requireActivity().isFinishing) {
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
if (!MessageDialogFragment.isDialogShowing()) {
dialog = MessageDialogFragment()
@@ -292,34 +349,11 @@ class MatterScannerFragment : Fragment() {
Timber.e("Unrecognized QR Exception")
}
} catch (e: Exception) {
- Timber.e("Unrecognized QR Exception $e" )
+ Timber.e("Unrecognized QR Exception $e")
}
}
- private fun navigateToThreadDevice(setupPayload: SetupPayload, isShortDiscriminator: Boolean) {
- FragmentUtils.getHost(this@MatterScannerFragment, CallBack::class.java)
- .setNetworkType(ProvisionNetworkType.THREAD)
- FragmentUtils.getHost(this@MatterScannerFragment, CallBack::class.java)
- .onChipDeviceInfoReceived(
- CHIPDeviceInfo.fromSetupPayload(
- setupPayload,
- isShortDiscriminator
- ), INPUT_NETWORK_THREAD_TYPE_SELECTED
- )
- }
-
- private fun navigateToWiFiDevice(setupPayload: SetupPayload, isShortDiscriminator: Boolean) {
- FragmentUtils.getHost(this@MatterScannerFragment, CallBack::class.java)
- .setNetworkType(ProvisionNetworkType.WIFI)
- FragmentUtils.getHost(this@MatterScannerFragment, CallBack::class.java)
- .onChipDeviceInfoReceived(
- CHIPDeviceInfo.fromSetupPayload(
- setupPayload,
- isShortDiscriminator
- ), INPUT_NETWORK_WIFI_TYPE_SELECTED
- )
- }
private fun aspectRatio(width: Int, height: Int): Int {
val previewRatio = max(width, height).toDouble() / min(width, height)
@@ -331,8 +365,7 @@ class MatterScannerFragment : Fragment() {
private fun hasCameraPermission(): Boolean {
return (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(
- requireContext(),
- Manifest.permission.CAMERA
+ requireContext(), Manifest.permission.CAMERA
))
}
@@ -352,20 +385,16 @@ class MatterScannerFragment : Fragment() {
}
private fun hasLocationPermission(): Boolean {
- val locationPermissionGranted =
- ContextCompat.checkSelfPermission(
- requireContext(),
- Manifest.permission.ACCESS_FINE_LOCATION
- ) == PackageManager.PERMISSION_GRANTED
+ val locationPermissionGranted = ContextCompat.checkSelfPermission(
+ requireContext(), Manifest.permission.ACCESS_FINE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
// Android 12 new permission
var bleScanPermissionGranted = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- bleScanPermissionGranted =
- ContextCompat.checkSelfPermission(
- requireContext(),
- Manifest.permission.BLUETOOTH_SCAN
- ) == PackageManager.PERMISSION_GRANTED
+ bleScanPermissionGranted = ContextCompat.checkSelfPermission(
+ requireContext(), Manifest.permission.BLUETOOTH_SCAN
+ ) == PackageManager.PERMISSION_GRANTED
}
return locationPermissionGranted && bleScanPermissionGranted
@@ -373,9 +402,7 @@ class MatterScannerFragment : Fragment() {
@Deprecated("Deprecated in Java")
override fun onRequestPermissionsResult(
- requestCode: Int,
- permissions: Array,
- grantResults: IntArray
+ requestCode: Int, permissions: Array, grantResults: IntArray
) {
if (requestCode == REQUEST_CODE_CAMERA_PERMISSION) {
if (grantResults.size == 1 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
@@ -390,16 +417,6 @@ class MatterScannerFragment : Fragment() {
}
}
- private fun showBluetoothEnableAlert() {
- AlertDialog.Builder(requireContext())
- .setTitle(R.string.toast_bluetooth_not_enabled)
- .setMessage(R.string.bluetooth_adapter_bar_turning_on)
- .setPositiveButton(R.string.matter_camera_unavailable_alert_exit) { _, _ ->
- requireActivity().finish()
- }
- .setCancelable(false)
- .create().show()
- }
private fun showCameraPermissionAlert() {
AlertDialog.Builder(requireContext())
@@ -407,9 +424,7 @@ class MatterScannerFragment : Fragment() {
.setMessage(R.string.matter_camera_unavailable_alert_subtitle)
.setPositiveButton(R.string.matter_camera_unavailable_alert_exit) { _, _ ->
requireActivity().finish()
- }
- .setCancelable(false)
- .create().show()
+ }.setCancelable(false).create().show()
}
private fun showLocationPermissionAlert() {
@@ -418,24 +433,228 @@ class MatterScannerFragment : Fragment() {
.setMessage(R.string.matter_location_unavailable_alert_subtitle)
.setPositiveButton(R.string.matter_camera_unavailable_alert_exit) { _, _ ->
requireActivity().finish()
- }
- .setCancelable(false)
- .create().show()
+ }.setCancelable(false).create().show()
}
+ @RequiresApi(Build.VERSION_CODES.R)
+ @Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
+
+ deviceInfo = CHIPDeviceInfo.fromSetupPayload(
+ payload, isShortDiscriminator
+ )
if (resultCode == WIFI_REQ_CODE) {
println("Matter Wifi Selected")
+ typeNtw = INPUT_NETWORK_WIFI_TYPE_SELECTED
networkMode = data!!.getStringExtra(ARG_PROVISION_NETWORK_TYPE).toString()
- navigateToWiFiDevice(payload, isShortDiscriminator)
+ displayCommissioningDialog()
+
} else if (resultCode == THREAD_REQ_CODE) {
println("Matter Thread Selected")
+ typeNtw = INPUT_NETWORK_THREAD_TYPE_SELECTED
networkMode = data!!.getStringExtra(ARG_PROVISION_NETWORK_TYPE).toString()
- navigateToThreadDevice(payload, isShortDiscriminator)
+ displayCommissioningDialog()
+
} else if (resultCode == CANCEL_REQ_CODE) {
cancelNetworkInputDialog()
startCamera()
+ } else if (resultCode == INPUT_WIFI_REQ_CODE) {
+ if (data != null) {
+ val wifiSSID = data.getStringExtra(WIFI_INPUT_SSID)
+ val wifiPassword = data.getStringExtra(WIFI_INPUT_PASSWORD)
+
+ if (wifiSSID != null && wifiPassword != null) {
+ validateWiFiInput(wifiSSID, wifiPassword)
+ }
+ }
+ } else if (resultCode == Activity.RESULT_OK) {
+ if (data != null) {
+ val receiveOTBRInfo = data.getStringExtra(DIALOG_OTBR_INFO)
+ removeAlert()
+ validateThreadInput(receiveOTBRInfo!!.trim())
+ }
+ }
+ }
+
+ private fun displayCommissioningDialog() {
+ val str = requireContext().getString(R.string.matter_commissioning_device)
+ showMatterProgressDialog(str, false)
+ CoroutineScope(Dispatchers.IO).launch {
+ delay(COMMISSIONING_DIALOG_TIME_OUT)
+ removeProgress()
+ displayInputWindowBasedOnProvisionType()
+ }
+ }
+
+ @SuppressLint("NewApi")
+ private fun validateThreadInput(inputOTBR: String) {
+ if (inputOTBR.isBlank()) {
+ Toast.makeText(requireContext(), "input OTBR is empty", Toast.LENGTH_SHORT).show()
+ return
+ }
+ val operationalDataset = dataFromHexString(inputOTBR.trim())
+
+ networkCredential = NetworkCredentialsParcelable.forThread(
+ NetworkCredentialsParcelable.ThreadCredentials(operationalDataset)
+ )
+ startConnectingToDevice()
+ }
+
+ @RequiresApi(Build.VERSION_CODES.R)
+ private fun validateWiFiInput(wifiSSID: String, wifiPassword: String) {
+ networkCredential = NetworkCredentialsParcelable.forWiFi(
+ NetworkCredentialsParcelable.WiFiCredentials(
+ wifiSSID, wifiPassword
+ )
+ )
+ startConnectingToDevice()
+ }
+
+
+ private fun dataFromHexString(string: String): ByteArray {
+ var modifiedString = string
+ if (string.length % 2 == 1) {
+ modifiedString = "0$string"
+ }
+
+ val chars = modifiedString.toCharArray()
+ var i = 0
+ val len = modifiedString.length
+
+
+ val data = ByteArray(len / 2)
+ val byteChars = CharArray(2)
+
+
+ while (i < len) {
+ byteChars[0] = chars[i++]
+ byteChars[1] = chars[i++]
+ var wholeByte = 0L
+ try {
+ wholeByte = byteChars.joinToString("").toLong(16)
+
+ } catch (ex: NumberFormatException) {
+ var wholeByte = 0L
+ Timber.tag(TAG).e("Number Format Exception Occurred..")
+ }
+
+ data[(i - 2) / 2] = wholeByte.toByte()
+ }
+
+ return data
+ }
+
+ @RequiresApi(Build.VERSION_CODES.R)
+ @SuppressLint("MissingPermission")
+ private fun startConnectingToDevice() {
+ if (gatt != null) {
+ return
+ }
+ scope.launch {
+
+ bluetoothManager = BluetoothManager()
+ val strId = R.string.rendezvous_over_ble_scanning_text
+ val devInfo = deviceInfo.discriminator.toString()
+ showMessage(strId, devInfo)
+ showMatterProgressDialog(
+ getString(R.string.matter_network_selection_alert_title), true
+ )
+ val device = bluetoothManager.getBluetoothDevice(
+ requireContext(), deviceInfo.discriminator, deviceInfo.isShortDiscriminator
+ ) ?: kotlin.run {
+ requireActivity().supportFragmentManager.popBackStack()
+ requireActivity().supportFragmentManager.popBackStack()
+ if (customProgressDialog != null) {
+ if (customProgressDialog!!.isShowing) {
+ customProgressDialog!!.dismiss()
+ }
+ }
+ showMessage(R.string.rendezvous_over_ble_scanning_failed_text)
+ return@launch
+ }
+ matterScanDevice = device
+ Timber.tag(TAG).e("Type : ${device.type}")
+ Timber.tag(TAG).e("UUID : ${device.uuids}")
+ Timber.tag(TAG).e("Name : ${device.name}")
+ Timber.tag(TAG).e("Address : ${device.address}")
+ Timber.tag(TAG).e("Alias : ${device.alias}")
+ if (customProgressDialog != null) {
+ if (customProgressDialog!!.isShowing) {
+ customProgressDialog!!.dismiss()
+ }
+ }
+ showMatterProgressDialog(
+ getString(R.string.matter_commissioning_message), true
+ )
+ showMessage(
+ R.string.rendezvous_over_ble_connecting_text,
+ device.name ?: device.address.toString()
+ )
+ removeAlert()
+ deviceId = DeviceIDUtil.getNextAvailableId(requireContext())
+ gatt = bluetoothManager.connect(requireContext(), device)
+ deviceController.setCompletionListener(ConnectionCallback())
+ val connId = bluetoothManager.connectionId
+ var network: NetworkCredentials? = null
+
+
+ val thread = networkCredential.threadCredentials
+ if (thread != null) {
+ network = NetworkCredentials.forThread(
+ NetworkCredentials.ThreadCredentials(thread.operationalDataset)
+ )
+ }
+ val wifi = networkCredential.wiFiCredentials
+ if (wifi != null) {
+ network = NetworkCredentials.forWiFi(
+ NetworkCredentials.WiFiCredentials(wifi.ssid, wifi.password)
+ )
+ }
+
+ setAttestationDelegate()
+
+ deviceController.pairDevice(
+ gatt, connId, deviceId, deviceInfo.setupPinCode, network
+ )
+ DeviceIDUtil.setNextAvailableId(requireContext(), deviceId + 1)
+ }
+ }
+
+ private fun setAttestationDelegate() {
+ deviceController.setDeviceAttestationDelegate(DEVICE_ATTESTATION_FAILED_TIMEOUT) { devicePtr, _, errorCode ->
+ Timber.tag(TAG).e(
+ "Device attestation errorCode: $errorCode, \nLook at 'src/credentials/attestation_verifier/DeviceAttestationVerifier.h' \nAttestationVerificationResult enum to understand the errors"
+ )
+
+ val activity = requireActivity()
+ Timber.tag(TAG).e("setAttestationDelegate()--errorCode: $errorCode")
+ if (errorCode == STATUS_PAIRING_SUCCESS) {
+ Timber.tag(TAG).e("setAttestationDelegate() In--errorCode: $errorCode")
+ activity.runOnUiThread {
+ deviceController.continueCommissioning(devicePtr, true)
+ }
+
+ return@setDeviceAttestationDelegate
+ }
+ activity.runOnUiThread(Runnable {
+ if (alertDialog != null && alertDialog?.isShowing == true) {
+ Timber.tag(TAG).e("Dialog is already showing...")
+ return@Runnable
+ }
+ alertDialog = android.app.AlertDialog.Builder(activity).setPositiveButton(
+ "Continue"
+ ) { alertDialog, id ->
+ deviceController.continueCommissioning(devicePtr, true)
+ }.setNegativeButton(
+ "No"
+ ) { alertDialog, id ->
+ deviceController.continueCommissioning(devicePtr, false)
+ }.setTitle("Device Attestation")
+ .setMessage("Device Attestation failed for device under commissioning. Do you wish to continue pairing?")
+ .show()
+ })
+
}
}
@@ -445,6 +664,12 @@ class MatterScannerFragment : Fragment() {
}
}
+ private fun removeAlert() {
+ if (otbrEntryDialog != null) {
+ otbrEntryDialog!!.dismiss()
+ }
+ }
+
override fun onDestroyView() {
super.onDestroyView()
cancelNetworkInputDialog()
@@ -456,33 +681,40 @@ class MatterScannerFragment : Fragment() {
}
}
+ private fun showMessage(msgResId: Int, stringArgs: String? = null) {
+ requireActivity().runOnUiThread {
+ val context = requireContext()
+ val msg = context.getString(msgResId, stringArgs)
+ Timber.tag(TAG).e("showMessage:$msg")
+ Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
+ }
+ }
+
private fun showDeviceInfoDialog(message: String) {
try {
- if (isAdded && requireActivity() != null && !requireActivity().isFinishing) {
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
- if (!deviceInfodialogShown && (deviceDialog == null || !deviceDialog!!.isShowing())) {
- deviceInfodialogShown=true
+ if (!deviceInfoDialogShown && (deviceDialog == null || !deviceDialog!!.isShowing())) {
+ deviceInfoDialogShown = true
deviceDialog = DialogDeviceInfoFragment.Builder()
- .setTitle(getString(R.string.qr_code_info))
- .setMessage(message)
+ .setTitle(getString(R.string.qr_code_info)).setMessage(message)
.setPositiveButton(getString(R.string.start_commissioning)) { dialog, which ->
// Positive button click logic
networkSelectionDialog =
MatterNetworkSelectionInputDialogFragment.newInstance()
- networkSelectionDialog!!.setTargetFragment(this, DIALOG_NTW_MODE_FRAGMENT)
+ networkSelectionDialog!!.setTargetFragment(
+ this, DIALOG_NTW_MODE_FRAGMENT
+ )
networkSelectionDialog!!.show(
- requireActivity().supportFragmentManager, ALERT_NTW_MODE_DIALOG_TAG
+ requireActivity().supportFragmentManager,
+ ALERT_NTW_MODE_DIALOG_TAG
)
- deviceDialog?.isShowing()==false
- deviceInfodialogShown=false
- }
- .setNegativeButton("Cancel") { dialog, which ->
+ deviceInfoDialogShown = false
+ }.setNegativeButton("Cancel") { dialog, which ->
deviceDialog?.dismiss()
- deviceDialog?.isShowing()==false
- deviceInfodialogShown=false
- }
- .build()
+ deviceInfoDialogShown = false
+ }.build()
deviceDialog?.show(parentFragmentManager, "DialogDeviceInfoFragment")
}
@@ -495,30 +727,306 @@ class MatterScannerFragment : Fragment() {
}
}
- interface CallBack {
- fun onChipDeviceInfoReceived(deviceInfo: CHIPDeviceInfo, ntwInputType: String)
+ private fun displayInputWindowBasedOnProvisionType() {
+ when (typeNtw) {
+ INPUT_NETWORK_WIFI_TYPE_SELECTED /* ProvisionNetworkType.WIFI */ -> {
+ if (wifiEntryDialog == null) {
+ val prev = requireActivity().supportFragmentManager.findFragmentByTag(
+ DIALOG_WIFI_INPUT_TAG
+ )
+ if (prev == null) {
+ wifiEntryDialog = MatterWifiInputDialogFragment.newInstance()
+ wifiEntryDialog!!.setTargetFragment(this, DIALOG_WIFI_FRAGMENT)
+ wifiEntryDialog!!.show(
+ requireActivity().supportFragmentManager, DIALOG_WIFI_INPUT_TAG
+ )
+ }
+ }
+ }
+
+ INPUT_NETWORK_THREAD_TYPE_SELECTED /* ProvisionNetworkType.THREAD*/ -> {
+ if (otbrEntryDialog == null) {
+ val prev = requireActivity().supportFragmentManager.findFragmentByTag(
+ DIALOG_THREAD_INPUT_TAG
+ )
+ if (prev == null) {
+ otbrEntryDialog = MatterOTBRInputDialogFragment.newInstance()
+
+ otbrEntryDialog!!.setTargetFragment(this, DIALOG_THREAD_FRAGMENT)
+ otbrEntryDialog!!.show(
+ requireActivity().supportFragmentManager, DIALOG_THREAD_INPUT_TAG
+ )
+ }
+ }
+ }
+
+ else -> {
+ println("Unhandled....")
+ }
+
+ }
+ }
+
+ private fun showMatterProgressDialog(message: String, showCancelButton: Boolean) {
+ customProgressDialog = CustomProgressDialog(requireContext())
+ customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
+ customProgressDialog!!.setCustomButtonVisible(showCancelButton) {
+ deviceController.close()
+ requireActivity().supportFragmentManager.popBackStack(
+ null, FragmentManager.POP_BACK_STACK_INCLUSIVE
+ )
+ sendToScanResultFragment()
+
+ customProgressDialog!!.dismiss()
+ }
+ customProgressDialog!!.show()
+ }
+
+ private fun sendToScanResultFragment() {
+ val bundle = Bundle()
+ scannedDeviceList = SharedPrefsUtils.retrieveSavedDevices(mPrefs)
+ bundle.putParcelableArrayList(ARG_DEVICE_LIST, scannedDeviceList)
+
+
+ val fragment = MatterScannedResultFragment.newInstance()
+ fragment.arguments = bundle
+
+ parentFragmentManager.beginTransaction().replace(
+ R.id.matter_container, fragment
+ ) // R.id.matterContainer should be the container in the activity or fragment layout where the new fragment will be placed
+ .addToBackStack(null) // Add to back stack if you want the user to be able to navigate back
+ .commit()
+ }
+
+ private fun removeProgress() {
+ if (customProgressDialog?.isShowing == true) {
+ customProgressDialog?.dismiss()
+ }
+ }
+
+ private fun onCommissionCompleted() {
+ try {
+ ChipClient.getDeviceController(requireContext()).close()
+ } catch (e: Exception) {
+ Timber.tag(TAG).e("onCommissionCompleted error $e")
+ }
+ }
+
+ inner class ConnectionCallback : GenericChipDeviceListener() {
+ override fun onConnectDeviceComplete() {
+ super.onConnectDeviceComplete()
+ Timber.tag(TAG).e("onConnectDeviceComplete")
+ }
+
+ override fun onStatusUpdate(status: Int) {
+ super.onStatusUpdate(status)
+ Timber.tag(TAG).e("onStatusUpdate : $status.toString()")
+ }
+
+ private suspend fun getDescriptorClusterForDevice(): ChipClusters.DescriptorCluster {
+ return ChipClusters.DescriptorCluster(
+
+ ChipClient.getConnectedDevicePointer(requireContext(), deviceId),
+ ON_OFF_CLUSTER_ENDPOINT
+ )
+ }
+
+ @SuppressLint("MissingPermission")
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
+ super.onCommissioningComplete(nodeId, errorCode)
+ Timber.tag(TAG).e("onCommissioningComplete : NodeID: $nodeId.toString()")
+ Timber.tag(TAG).e("%s%s", "onCommissioningComplete : errorCode: ", errorCode.toString())
+ removeAlert()
+ if (errorCode == STATUS_PAIRING_SUCCESS) {
+ if (customProgressDialog?.isShowing == true) {
+ customProgressDialog?.dismiss()
+ }
+ Timber.tag(TAG).e("pairing success")
+ onCommissionCompleted()
+
+ scope.launch {
+ getDescriptorClusterForDevice().readDeviceTypeListAttribute(object :
+ ChipClusters.DescriptorCluster.DeviceTypeListAttributeCallback {
+ override fun onError(error: java.lang.Exception?) {
+ Timber.tag(TAG).e("MatterConnect Error: $error")
+ }
+
+ override fun onSuccess(valueList: MutableList?) {
+
+ Timber.tag(TAG)
+ .e("deviceType $ valueList?.get(0)?.deviceType?.toInt()!!")
+ val deviceType = valueList?.get(0)?.deviceType?.toInt()!!
+ println("device Type: $deviceType}")
+ println("device Info: ${matterScanDevice.name} DeviceId: ${deviceId}")
+ var device = ""
+
+ when (deviceType) {
+ DOOR_LOCK_TYPE -> device =
+ requireContext().getString(R.string.matter_lock_list)
+
+ DIMMABLE_PLUG_IN_UNIT_TYPE -> device =
+ requireContext().getString(R.string.matter_plug_list)
+
+ OCCUPANCY_SENSOR_TYPE -> device =
+ requireContext().getString(R.string.matter_occupancy_sensor_list)
- fun setNetworkType(type: ProvisionNetworkType)
+ TEMPERATURE_SENSOR_TYPE -> device =
+ requireContext().getString(R.string.matter_temperature_sensor_list)
+
+ CONTACT_SENSOR_TYPE -> device =
+ requireContext().getString(R.string.matter_contact_sensor_list)
+
+ THERMOSTAT_TYPE -> device =
+ requireContext().getString(R.string.matter_thermostat_list)
+
+ DIMMABLE_LIGHT_TYPE, ENHANCED_COLOR_LIGHT_TYPE, ON_OFF_LIGHT_TYPE, COLOR_TEMPERATURE_LIGHT_TYPE -> device =
+ requireContext().getString(R.string.matter_light_list)
+
+ WINDOW_COVERING_TYPE -> device =
+ requireContext().getString(R.string.matter_window_list)
+
+ DISHWASHER_TYPE -> device =
+ requireContext().getString(R.string.matter_dishwahser_list)
+
+ else -> device = matterScanDevice.name
+
+
+ // else -> device = matterScanDevice.name
+ }
+
+ val deviceName = device + COLON_WITH_SPACE + deviceId
+ println("device Info: ${deviceName} DeviceId: ${deviceId}")
+
+ showEditDeviceNameDialog(device, valueList)
+
+
+ }
+
+ private fun showEditDeviceNameDialog(
+ device: String,
+ valueList: MutableList
+ ) {
+
+ val customInputDialog = CustomInputDialog.newInstance(
+ requireContext(),
+ device,
+ getString(R.string.add_device_name),
+ getString(
+ R.string.add_device_subtitle
+ )
+ )
+ customInputDialog.setOnButtonClickListener { deviceName ->
+
+ val matterInfo = MatterScannedResultModel(
+ deviceName,
+ matterScanDevice.address,
+ matterScanDevice.type,
+ deviceId,
+ valueList.get(0).deviceType?.toInt()!!,
+ isDeviceOnline = true
+ )
+ FragmentUtils.getHost(
+ this@MatterScannerFragment, CallBack::class.java
+ ).onCommissionCompleteLoadData(matterInfo)
+ }
+
+ customInputDialog.show(requireFragmentManager(), "CustomInputDialog")
+
+
+ }
+
+ })
+ }
+
+
+ } else {
+ if (customProgressDialog?.isShowing() == true) {
+ customProgressDialog?.dismiss()
+ }
+ requireActivity().runOnUiThread {
+ showAlertWindow(errorCode)
+ }
+ }
+ onCommissionCompleted()
+ }
+ }
+
+ private fun showAlertWindow(errorCode: Long) {
+ val builder = android.app.AlertDialog.Builder(context, R.style.AlertDialogTheme)
+ val alertMessageStart =
+ requireContext().getString(R.string.matter_device_commissioning_failed)
+ val alertTitle = requireContext().getString(R.string.matter_delete_alert_title)
+
+
+ builder.setTitle(alertTitle)
+ builder.setMessage(alertMessageStart)
+ builder.setPositiveButton(
+ requireContext().getString(R.string.matter_alert_ok)
+ ) { dialog: DialogInterface?, which: Int ->
+ // When the user click yes button then app will close
+ dialog?.dismiss()
+ requireActivity().supportFragmentManager.popBackStack()
+ }
+ builder.setNegativeButton(
+ requireContext().getString(R.string.matter_cancel)
+ ) { dialog: DialogInterface?, which: Int ->
+ // When the user click yes button then app will close
+ dialog?.dismiss()
+ requireActivity().supportFragmentManager.popBackStack()
+ }
+ builder.show()
+
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ stopCamera()
+ }
+
+
+ interface CallBack {
+ fun onCommissionCompleteLoadData(
+ matterScannedResultModel: MatterScannedResultModel
+ )
}
companion object {
private val TAG = MatterScannerFragment::class.java.classes.toString()
+ private const val COMMISSIONING_DIALOG_TIME_OUT = 1000L
+ const val CANCEL_REQ_CODE = 5000
+ const val WIFI_REQ_CODE = 5001
+ const val THREAD_REQ_CODE = 5002
+ const val INPUT_WIFI_REQ_CODE = 5003
+ private const val DEVICE_ATTESTATION_FAILED_TIMEOUT = 600
+ private const val DIALOG_THREAD_FRAGMENT = 999
+ private const val DIALOG_WIFI_FRAGMENT = 997
+
+ private const val STATUS_PAIRING_SUCCESS = 0L
+
private const val REQUEST_CODE_LOCATION_PERMISSION = 101
private const val REQUEST_CODE_CAMERA_PERMISSION = 100
private const val RATIO_4_3_VALUE = 4.0 / 3.0
private const val RATIO_16_9_VALUE = 16.0 / 9.0
private const val DIALOG_NTW_MODE_FRAGMENT = 998
- const val CANCEL_REQ_CODE = 5000
- const val WIFI_REQ_CODE = 5001
- const val THREAD_REQ_CODE = 5002
- const val INPUT_WIFI_REQ_CODE = 5003
+
+ const val SPACE = " "
const val INPUT_NETWORK_WIFI_TYPE_SELECTED = "wifi"
const val INPUT_NETWORK_THREAD_TYPE_SELECTED = "thread"
const val WIFI_INPUT_SSID = "wifi_input_ssid"
const val WIFI_INPUT_PASSWORD = "wifi_input_password"
const val ARG_PROVISION_NETWORK_TYPE = "dialog_network_mode_info"
+ const val DIALOG_OTBR_INFO = "Dialog_OTBR_Info"
+ const val DIA_INPUT_NTW_TYPE = "dia_input_ntw_type"
+
+ private const val COLON_WITH_SPACE = " - "
private const val ALERT_NTW_MODE_DIALOG_TAG = "alert_ntw_mode_dialog_tag"
+ private const val DIALOG_THREAD_INPUT_TAG = "MatterThreadDialogFragmentTAG"
+ private const val DIALOG_WIFI_INPUT_TAG = "MatterWiFiDialogFragmentTAG"
+ private const val ARG_DEVICE_LIST = "device_list"
+
fun newInstance(): MatterScannerFragment {
val args = Bundle()
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 4bf3fa9b..38c5b8d0 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
@@ -27,6 +27,7 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.controller.GenericChipD
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ARG_DEVICE_MODEL
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.INIT
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ON_OFF_CLUSTER_ENDPOINT
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannerFragment.Companion.SPACE
import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
@@ -60,7 +61,7 @@ class MatterTemperatureSensorFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mPrefs = requireContext().getSharedPreferences(
- "your_preference_name",
+ MatterDemoActivity.MATTER_PREF,
AppCompatActivity.MODE_PRIVATE
)
model = requireArguments().getParcelable(ARG_DEVICE_MODEL)!!
@@ -68,14 +69,13 @@ class MatterTemperatureSensorFragment : Fragment() {
if (deviceId != null) {
- showMatterProgressDialog(getString(R.string.please_wait))
+ showMatterProgressDialog(getString(R.string.matter_device_status))
- // retrieveSavedDevices()
- GlobalScope.launch {
+ CoroutineScope(Dispatchers.IO).launch {
// This code will run asynchronously
- val resultq = checkForDeviceStatus()
- if (resultq) {
+ val resInfo = checkForDeviceStatus()
+ if (resInfo) {
println("Operation was successful")
removeProgress()
}
@@ -114,17 +114,10 @@ class MatterTemperatureSensorFragment : Fragment() {
}
}
- override fun onAttach(@NotNull context: Context) {
- super.onAttach(context)
- }
-
- override fun onDetach() {
- super.onDetach()
- }
private fun showMessageDialog() {
try {
- if (isAdded() && requireActivity() != null && !requireActivity().isFinishing) {
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
if (!MessageDialogFragment.isDialogShowing()) {
dialog = MessageDialogFragment()
@@ -137,8 +130,7 @@ class MatterTemperatureSensorFragment : Fragment() {
FragmentUtils.getHost(
this@MatterTemperatureSensorFragment,
CallBackHandler::class.java
- )
- .onBackHandler()
+ ).onBackHandler()
}
}
val transaction: FragmentTransaction =
@@ -151,14 +143,14 @@ class MatterTemperatureSensorFragment : Fragment() {
Timber.e("device offline")
}
} catch (e: Exception) {
- Timber.e("" + e)
+ Timber.e("Exception Occurred $e")
}
}
private fun removeProgress() {
- if (customProgressDialog?.isShowing() == true) {
+ if (customProgressDialog?.isShowing == true) {
customProgressDialog?.dismiss()
}
}
@@ -167,6 +159,7 @@ class MatterTemperatureSensorFragment : Fragment() {
customProgressDialog = CustomProgressDialog(requireContext())
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.show()
}
@@ -174,7 +167,7 @@ class MatterTemperatureSensorFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
binding = FragmentMatterTemperatureSensorBinding.inflate(inflater, container, false)
return binding.root
@@ -195,8 +188,8 @@ class MatterTemperatureSensorFragment : Fragment() {
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(
this@MatterTemperatureSensorFragment,
@@ -287,7 +280,7 @@ class MatterTemperatureSensorFragment : Fragment() {
}
override fun onError(ex: Exception?) {
- Timber.e(TAG, "read local temp command failure", ex)
+ Timber.e(TAG, "read local temp command failure :$ex")
// removeProgress()
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
showMessageDialog()
@@ -301,16 +294,16 @@ class MatterTemperatureSensorFragment : Fragment() {
@SuppressLint("SetTextI18n")
override fun onSuccess(value: Int?) {
// removeProgress()
- requireActivity().runOnUiThread(Runnable {
+ requireActivity().runOnUiThread {
val resValue = addDecimalPointToInteger(value)
binding.txtValue.text = SPACE + (resValue) + TEMPERATURE_UNIT
- })
+ }
}
- override fun onError(ex: java.lang.Exception?) {
+ override fun onError(exe: java.lang.Exception?) {
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
- Timber.tag(TAG).e( "read local temp command failure"+ ex)
+ Timber.tag(TAG).e("read local temp command failure :$exe")
showMessageDialog()
}
@@ -330,7 +323,7 @@ class MatterTemperatureSensorFragment : Fragment() {
inner class TempSensorChipControllerCallback : GenericChipDeviceListener() {
override fun onConnectDeviceComplete() {}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
Timber.d(TAG, "onCommissioningComplete for nodeId $nodeId: $errorCode")
//showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}
@@ -343,7 +336,7 @@ class MatterTemperatureSensorFragment : Fragment() {
Timber.d(TAG, "onCloseBleComplete")
}
- override fun onError(error: Throwable) {
+ override fun onError(error: Throwable?) {
super.onError(error)
Timber.d(TAG, "onError : $error")
}
@@ -357,9 +350,8 @@ class MatterTemperatureSensorFragment : Fragment() {
const val MIN_REFRESH_PERIOD_S = 2
const val MAX_REFRESH_PERIOD_S = 10
const val TEMPERATURE_UNIT = " \u2103"
- const val SPACE = ""
- private val TAG = MatterTemperatureSensorFragment.javaClass.simpleName.toString()
+ private val TAG = Companion::class.java.simpleName.toString()
fun newInstance(): MatterTemperatureSensorFragment = MatterTemperatureSensorFragment()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterThermostatFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterThermostatFragment.kt
index 4e365b33..b75ad6e7 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterThermostatFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterThermostatFragment.kt
@@ -1,11 +1,10 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.fragments
-import android.content.Context
+import android.annotation.SuppressLint
import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -23,13 +22,11 @@ import com.siliconlabs.bledemo.bluetooth.beacon_utils.eddystone.Constants
import com.siliconlabs.bledemo.databinding.FragmentMatterThermostatBinding
import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoActivity
import com.siliconlabs.bledemo.features.demo.matter_demo.controller.GenericChipDeviceListener
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterConnectFragment.Companion.SPACE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ARG_DEVICE_INFO
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ARG_DEVICE_MODEL
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.INIT
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ON_OFF_CLUSTER_ENDPOINT
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannerFragment.Companion.SPACE
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterTemperatureSensorFragment.Companion.TEMPERATURE_UNIT
-import com.siliconlabs.bledemo.features.demo.matter_demo.model.CHIPDeviceInfo
import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
@@ -38,13 +35,10 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFrag
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.jetbrains.annotations.NotNull
import timber.log.Timber
-import java.text.DecimalFormat
class MatterThermostatFragment : Fragment() {
@@ -63,28 +57,26 @@ class MatterThermostatFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mPrefs = requireContext().getSharedPreferences(
- "your_preference_name",
+ MatterDemoActivity.MATTER_PREF,
AppCompatActivity.MODE_PRIVATE
)
if (requireArguments() != null) {
model = requireArguments().getParcelable(ARG_DEVICE_MODEL)!!
deviceId = model.deviceId
- Timber.tag(TAG).e( "deviceID: " + model)
+ Timber.tag(TAG).e("deviceID: $model")
}
if (deviceId != null) {
- showMatterProgressDialog(getString(R.string.please_wait))
+ showMatterProgressDialog(getString(R.string.matter_device_status))
// retrieveSavedDevices()
- GlobalScope.launch {
+ CoroutineScope(Dispatchers.IO).launch {
// This code will run asynchronously
- val resultq = checkForDeviceStatus()
- if (resultq) {
+ val resInfo = checkForDeviceStatus()
+ if (resInfo) {
println("Operation was successful")
removeProgress()
- // prepareList()
-
}
}
}
@@ -118,30 +110,23 @@ class MatterThermostatFragment : Fragment() {
}
}
- override fun onAttach(@NotNull context: Context) {
- super.onAttach(context)
- }
- override fun onDetach() {
- super.onDetach()
- }
private fun showMessageDialog() {
try {
- if (isAdded() && requireActivity()!=null && !requireActivity().isFinishing){
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
if (!MessageDialogFragment.isDialogShowing()) {
dialog = MessageDialogFragment()
dialog.setMessage(getString(R.string.matter_device_offline_text))
dialog.setOnDismissListener {
removeProgress()
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(
this@MatterThermostatFragment,
MatterDoorFragment.CallBackHandler::class.java
- )
- .onBackHandler()
+ ).onBackHandler()
}
}
val transaction: FragmentTransaction =
@@ -150,18 +135,18 @@ class MatterThermostatFragment : Fragment() {
dialog.show(transaction, dialogTag)
}
}
- }else{
+ } else {
Timber.e("device offline")
}
- }catch (e:Exception){
- Timber.e("device offline"+e)
+ } catch (e: Exception) {
+ Timber.e("device offline $e")
}
}
private fun removeProgress() {
- if (customProgressDialog?.isShowing() == true) {
+ if (customProgressDialog?.isShowing == true) {
customProgressDialog?.dismiss()
}
}
@@ -170,6 +155,7 @@ class MatterThermostatFragment : Fragment() {
customProgressDialog = CustomProgressDialog(requireContext())
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.show()
}
@@ -189,8 +175,8 @@ class MatterThermostatFragment : Fragment() {
scope = viewLifecycleOwner.lifecycleScope
deviceController.setCompletionListener(DoorChipControllerCallback())
- binding.btnReadValue.setLongClickable(false);
- binding.btnReadValue.setText(requireContext().getText(R.string.matter_temp_refresh))
+ binding.btnReadValue.isLongClickable = false
+ binding.btnReadValue.text = requireContext().getText(R.string.matter_temp_refresh)
binding.btnReadValue.setOnClickListener {
scope.launch { sendReadValueCommandClick() }
@@ -200,8 +186,8 @@ class MatterThermostatFragment : Fragment() {
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(this@MatterThermostatFragment, CallBackHandler::class.java)
.onBackHandler()
@@ -242,26 +228,26 @@ class MatterThermostatFragment : Fragment() {
private suspend fun sendReadValueCommandClick() {
getThermostatClusterForDevice().readLocalTemperatureAttribute(object :
ChipClusters.ThermostatCluster.LocalTemperatureAttributeCallback {
+ @SuppressLint("SetTextI18n")
override fun onSuccess(value: Int?) {
- SharedPrefsUtils.updateDeviceByDeviceId(mPrefs,deviceId,true)
- requireActivity().runOnUiThread(Runnable {
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
+ requireActivity().runOnUiThread {
val resValue = roundDoubleToInt(addDecimalPointToInteger(value))
- Log.e(
- TAG,
- "read local temp command Success: " + addDecimalPointToInteger(value)
+ Timber.tag(TAG).e(
+ "read local temp command Success: ${addDecimalPointToInteger(value)}"
)
binding.txtValue.setText(SPACE + (resValue) + TEMPERATURE_UNIT)
- })
+ }
}
- override fun onError(ex: Exception?) {
- // removeProgress()
+ override fun onError(exe: Exception?) {
+ // removeProgress()
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
showMessageDialog()
- Timber.tag(TAG).e( "read local temp command failure", ex)
+ Timber.tag(TAG).e("read local temp command failure:$exe")
}
})
}
@@ -277,7 +263,7 @@ class MatterThermostatFragment : Fragment() {
inner class DoorChipControllerCallback : GenericChipDeviceListener() {
override fun onConnectDeviceComplete() {}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
Timber.d(TAG, "onCommissioningComplete for nodeId $nodeId: $errorCode")
//showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}
@@ -290,7 +276,7 @@ class MatterThermostatFragment : Fragment() {
Timber.d(TAG, "onCloseBleComplete")
}
- override fun onError(error: Throwable) {
+ override fun onError(error: Throwable?) {
super.onError(error)
Timber.d(TAG, "onError : $error")
}
@@ -301,7 +287,7 @@ class MatterThermostatFragment : Fragment() {
}
companion object {
- private val TAG = MatterThermostatFragment.javaClass.simpleName.toString()
+ private val TAG = Companion::class.java.simpleName.toString()
fun newInstance(): MatterThermostatFragment = MatterThermostatFragment()
}
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 8bc81c87..2105a212 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
@@ -11,7 +11,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
-import android.view.WindowManager
import android.widget.Toast
import androidx.fragment.app.DialogFragment
import com.siliconlabs.bledemo.R
@@ -32,7 +31,7 @@ class MatterWifiInputDialogFragment : DialogFragment() {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
if (!flag) {
flag = true
binding = DialogConfigureWifiMatterBinding.inflate(inflater, container, false)
@@ -40,6 +39,7 @@ class MatterWifiInputDialogFragment : DialogFragment() {
if (dialog != null && dialog!!.window != null) {
dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog!!.window!!.requestFeature(Window.FEATURE_NO_TITLE)
+ dialog!!.setCanceledOnTouchOutside(false)
}
return binding.root
}
@@ -65,15 +65,19 @@ class MatterWifiInputDialogFragment : DialogFragment() {
binding.positiveBtn.setOnClickListener {
val wifiSSID = binding.editNetworkSSID.text.toString().trim()
val wifiPassword = binding.editWiFiPassword.text.toString().trim()
- if (wifiSSID.isNullOrBlank() || wifiPassword.isNullOrBlank()) {
- Toast.makeText(requireContext(),
- getString(R.string.ssid_and_password_required), Toast.LENGTH_SHORT)
+ if (wifiSSID.isBlank() || wifiPassword.isBlank()) {
+ Toast.makeText(
+ requireContext(),
+ getString(R.string.ssid_and_password_required), Toast.LENGTH_SHORT
+ )
.show()
return@setOnClickListener
}
if (!FragmentUtils.isPasswordValid(wifiPassword)) {
- Toast.makeText(requireContext(),
- getString(R.string.password_must_be_min_8_characters), Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ requireContext(),
+ getString(R.string.password_must_be_min_8_characters), Toast.LENGTH_SHORT
+ ).show()
return@setOnClickListener
}
val intent = Intent()
@@ -103,9 +107,11 @@ class MatterWifiInputDialogFragment : DialogFragment() {
}
}
}
+
interface CallBackHandler {
fun onBackHandler()
}
+
private fun getScreenWidth(activity: Activity): Int {
val size = Point()
activity.windowManager.defaultDisplay.getSize(size)
@@ -120,4 +126,5 @@ class MatterWifiInputDialogFragment : DialogFragment() {
super.onDestroy()
flag = false
}
+
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterWindowCoverFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterWindowCoverFragment.kt
index aacef3b9..53cf8eae 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterWindowCoverFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterWindowCoverFragment.kt
@@ -1,11 +1,9 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.fragments
-import android.content.Context
import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -16,7 +14,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.ChipClusters
-import chip.devicecontroller.ChipClusters.IntegerAttributeCallback
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.GetConnectedDeviceCallbackJni
import com.siliconlabs.bledemo.R
@@ -26,6 +23,7 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoAc
import com.siliconlabs.bledemo.features.demo.matter_demo.controller.GenericChipDeviceListener
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ARG_DEVICE_MODEL
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.ON_OFF_CLUSTER_ENDPOINT
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterLightFragment.Companion.TIME_OUT
import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.ChipClient
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.CustomProgressDialog
@@ -34,11 +32,9 @@ import com.siliconlabs.bledemo.features.demo.matter_demo.utils.MessageDialogFrag
import com.siliconlabs.bledemo.features.demo.matter_demo.utils.SharedPrefsUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.jetbrains.annotations.NotNull
import timber.log.Timber
@@ -55,10 +51,11 @@ class MatterWindowCoverFragment : Fragment() {
private var endpointId: Int = ON_OFF_CLUSTER_ENDPOINT
private lateinit var model: MatterScannedResultModel
private lateinit var binding: FragmentMatterWindowCoverBinding
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mPrefs = requireContext().getSharedPreferences(
- "your_preference_name",
+ MatterDemoActivity.MATTER_PREF,
AppCompatActivity.MODE_PRIVATE
)
if (requireArguments() != null) {
@@ -72,9 +69,7 @@ class MatterWindowCoverFragment : Fragment() {
showMatterProgressDialog(getString(R.string.matter_device_status))
// retrieveSavedDevices()
- GlobalScope.launch {
- // This code will run asynchronously
-
+ CoroutineScope(Dispatchers.IO).launch {
val resultq = checkForDeviceStatus()
if (resultq) {
removeProgress()
@@ -88,36 +83,35 @@ class MatterWindowCoverFragment : Fragment() {
return withContext(Dispatchers.Default) {
// Simulate a time-consuming task
- deviceController.getConnectedDevicePointer(deviceId, object :
- GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback {
- override fun onDeviceConnected(devicePointer: Long) {
- Log.e(TAG, "devicePointer " + devicePointer + " nodeid " + deviceId)
- model.isDeviceOnline = true
- SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
- // removeProgress()
+ deviceController.getConnectedDevicePointer(deviceId,
+ object : GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback {
+ override fun onDeviceConnected(devicePointer: Long) {
+ Timber.tag(TAG)
+ .e("devicePointer :$devicePointer + nodeid :$deviceId")
+ model.isDeviceOnline = true
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
+ // removeProgress()
- }
+ }
- override fun onConnectionFailure(nodeId: Long, error: Exception?) {
- model.isDeviceOnline = false
- removeProgress()
- SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
+ override fun onConnectionFailure(nodeId: Long, error: Exception?) {
+ model.isDeviceOnline = false
+ removeProgress()
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
- showMessageDialog(getString(R.string.matter_device_offline_text))
- }
- })
+ showMessageDialog(getString(R.string.matter_device_offline_text))
+ }
+ })
delay(Constants.SCAN_TIMER * 500)
- //handleSubscriptionForWindowCover()
- // Return the result (true or false based on the actual result)
true
}
}
private suspend fun handleSubscriptionForWindowCover() {
getWindowClusterForDevice().subscribeModeAttribute(
- object : IntegerAttributeCallback {
+ object : ChipClusters.IntegerAttributeCallback {
override fun onSuccess(value: Int) {
println("value $value")
}
@@ -132,7 +126,7 @@ class MatterWindowCoverFragment : Fragment() {
}
private fun showMessageDialog(msg: String) {
- if (isAdded() && requireActivity() != null && !requireActivity().isFinishing) {
+ if (isAdded && !requireActivity().isFinishing) {
requireActivity().runOnUiThread {
if (!MessageDialogFragment.isDialogShowing()) {
dialog = MessageDialogFragment()
@@ -140,14 +134,13 @@ class MatterWindowCoverFragment : Fragment() {
dialog.setOnDismissListener {
removeProgress()
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(
this@MatterWindowCoverFragment,
CallBackHandler::class.java
- )
- .onBackHandler()
+ ).onBackHandler()
}
}
val transaction: FragmentTransaction =
@@ -172,13 +165,14 @@ class MatterWindowCoverFragment : Fragment() {
customProgressDialog = CustomProgressDialog(requireContext())
customProgressDialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
customProgressDialog!!.setMessage(message)
+ customProgressDialog!!.setCanceledOnTouchOutside(false)
customProgressDialog!!.show()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
+ ): View {
// Inflate the layout for this fragment
binding = FragmentMatterWindowCoverBinding.inflate(inflater, container, false)
return binding.root
@@ -189,36 +183,166 @@ class MatterWindowCoverFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
scope = viewLifecycleOwner.lifecycleScope
deviceController.setCompletionListener(WindowCoverChipControllerCallback())
- binding.btnMatterWindowState.setImageResource(R.drawable.window_close)
- binding.btnWindowClose.isLongClickable = false;
- binding.btnWindowOpen.isLongClickable = false;
+ scope.launch {
+ readTargetPositionLift()
+ readTargetPositionTilt()
+ }
+ binding.btnMatterWindowState.setImageResource(R.drawable.w0)
+ binding.overlayImage.setImageResource(R.drawable.w0)
+
+ binding.btnWindowClose.isLongClickable = false
+ binding.btnWindowOpen.isLongClickable = false
binding.btnWindowClose.text = requireContext().getText(R.string.matter_window_close)
binding.btnWindowOpen.text = requireContext().getText(R.string.matter_window_open)
+ binding.btnWindowLift.isLongClickable = false
+ binding.btnWindowLift.isLongClickable = false
+ binding.btnWindowLift.text = requireContext().getText(R.string.lift)
+
+ binding.btnWindowTilt.isLongClickable = false
+ binding.btnWindowTilt.isLongClickable = false
+ binding.btnWindowTilt.text = requireContext().getText(R.string.tilt)
+
binding.btnWindowOpen.setOnClickListener {
+ showMatterProgressDialog(getString(R.string.matter_door_lock_in_progress))
scope.launch {
sendWindowOpenCommandClick()
}
}
binding.btnWindowClose.setOnClickListener {
+ showMatterProgressDialog(getString(R.string.matter_door_lock_in_progress))
scope.launch {
sendWindowCloseCommandClick()
}
}
+
+ binding.btnWindowLift.setOnClickListener {
+ showMatterProgressDialog(getString(R.string.matter_door_lock_in_progress))
+ scope.launch {
+ if (!binding.etLift.text.isNullOrEmpty()) {
+ var liftPtage = binding.etLift.text.toString().toIntOrNull()
+ if (liftPtage != null && liftPtage in 1..100) {
+ liftPtage = 100 - liftPtage
+ sendWindowLiftCommandClick(liftPtage)
+ } else {
+ removeProgress()
+ showMessage(getString(R.string.enter_valid_lift_value_error))
+ }
+ } else {
+ removeProgress()
+ showMessage(getString(R.string.enter_lift_value_error))
+ }
+
+ }
+ }
+ binding.btnWindowTilt.setOnClickListener {
+ showMatterProgressDialog(getString(R.string.matter_door_lock_in_progress))
+ scope.launch {
+ if (!binding.etTilt.text.isNullOrEmpty()) {
+ var tiltPtage = binding.etTilt.text.toString().toIntOrNull()
+ if (tiltPtage != null && tiltPtage in 1..100) {
+ tiltPtage = 100 - tiltPtage
+ sendWindowTiltCommandClick(tiltPtage)
+ } else {
+ removeProgress()
+ showMessage(getString(R.string.enter_valid_tilt_value_error))
+ }
+ } else {
+ removeProgress()
+ showMessage(getString(R.string.enter_tilt_value_error))
+ }
+
+ }
+ }
(activity as MatterDemoActivity).hideQRScanner()
//back handling
- requireActivity().onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
+ requireActivity().onBackPressedDispatcher.addCallback(
+ viewLifecycleOwner,
+ onBackPressedCallback
+ )
+ }
+
+ private suspend fun readTargetPositionLift() {
+ getWindowClusterForDevice().readTargetPositionLiftPercent100thsAttribute(object :
+ ChipClusters.WindowCoveringCluster.TargetPositionLiftPercent100thsAttributeCallback {
+ override fun onSuccess(value: Int?) {
+ removeProgress()
+ // binding.etLift.setText(value?.div(100).toString())
+ when (value?.div(100)) {
+ 0 -> {
+ binding.btnMatterWindowState.setImageResource(R.drawable.w0)
+ scope.launch {
+ sendWindowOpenCommandClick()
+ }
+ }
+
+ in 1..10 -> binding.btnMatterWindowState.setImageResource(R.drawable.w1)
+ in 11..20 -> binding.btnMatterWindowState.setImageResource(R.drawable.w2)
+ in 21..30 -> binding.btnMatterWindowState.setImageResource(R.drawable.w3)
+ in 31..40 -> binding.btnMatterWindowState.setImageResource(R.drawable.w4)
+ in 41..50 -> binding.btnMatterWindowState.setImageResource(R.drawable.w5)
+ in 51..60 -> binding.btnMatterWindowState.setImageResource(R.drawable.w6)
+ in 61..70 -> binding.btnMatterWindowState.setImageResource(R.drawable.w7)
+ in 71..80 -> binding.btnMatterWindowState.setImageResource(R.drawable.w8)
+ in 81..90 -> binding.btnMatterWindowState.setImageResource(R.drawable.w9)
+ in 91..100 -> binding.btnMatterWindowState.setImageResource(R.drawable.w10)
+ else -> null
+ }
+ }
+
+ override fun onError(ex: java.lang.Exception?) {
+ removeProgress()
+ Timber.tag(TAG).e("Read LiftPercentage command failure: $ex")
+ }
+ })
+ }
+
+ private suspend fun readTargetPositionTilt() {
+ getWindowClusterForDevice().readTargetPositionTiltPercent100thsAttribute(object :
+ ChipClusters.WindowCoveringCluster.TargetPositionTiltPercent100thsAttributeCallback {
+ override fun onSuccess(value: Int?) {
+ removeProgress()
+ // binding.etTilt.setText(value?.div(100).toString())
+ when (value?.div(100)) {
+ in 0..10 -> binding.btnMatterWindowState.alpha = 0.1f
+
+ in 11..20 -> binding.btnMatterWindowState.alpha = 0.15f
+
+ in 21..30 -> binding.btnMatterWindowState.alpha = 0.25f
+
+ in 31..40 -> binding.btnMatterWindowState.alpha = 0.35f
+
+ in 41..50 -> binding.btnMatterWindowState.alpha = 0.45f
+
+ in 51..60 -> binding.btnMatterWindowState.alpha = 0.55f
+
+ in 61..70 -> binding.btnMatterWindowState.alpha = 0.65f
+
+ in 71..80 -> binding.btnMatterWindowState.alpha = 0.75f
+
+ in 81..90 -> binding.btnMatterWindowState.alpha = 0.85f
+
+ in 91..100 -> binding.btnMatterWindowState.alpha = 0.95f
+ }
+ }
+
+ override fun onError(ex: java.lang.Exception?) {
+ removeProgress()
+ Timber.tag(TAG).e("Read LiftPercentage command failure: $ex")
+ }
+
+ })
}
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
- if (requireActivity().supportFragmentManager.getBackStackEntryCount() > 0) {
- requireActivity().supportFragmentManager.popBackStack();
+ if (requireActivity().supportFragmentManager.backStackEntryCount > 0) {
+ requireActivity().supportFragmentManager.popBackStack()
} else {
FragmentUtils.getHost(this@MatterWindowCoverFragment, CallBackHandler::class.java)
.onBackHandler()
@@ -232,17 +356,19 @@ class MatterWindowCoverFragment : Fragment() {
getWindowClusterForDevice().downOrClose(
object : ChipClusters.DefaultClusterCallback {
override fun onSuccess() {
- Timber.tag(TAG).d( "downOrClose command Success")
+ Timber.tag(TAG).d("downOrClose command Success")
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
- binding.btnMatterWindowState.setImageResource(R.drawable.window_close)
+ binding.btnMatterWindowState.alpha = 1.0f
+ binding.btnMatterWindowState.setImageResource(R.drawable.w10)
+ removeProgress()
}
override fun onError(error: Exception?) {
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
showMessageDialog(getString(R.string.matter_device_offline_text))
-
- Log.e(TAG, "downOrClose command failure", error)
+ Timber.tag(TAG).e("downOrClose command failure: $error")
+ removeProgress()
}
}
@@ -254,23 +380,73 @@ class MatterWindowCoverFragment : Fragment() {
object : ChipClusters.DefaultClusterCallback {
override fun onSuccess() {
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
- Timber.tag(TAG).d( "upOrOpen command Success")
- binding.btnMatterWindowState.setImageResource(R.drawable.window_open)
+ Timber.tag(TAG).d("upOrOpen command Success")
+ removeProgress()
+ binding.btnMatterWindowState.setImageResource(R.drawable.w0)
}
override fun onError(error: Exception?) {
SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
showMessageDialog(getString(R.string.matter_device_offline_text))
- // showMessage("Matter device is offline")
- // showMessage("upOrOpen command failure $error")
- Log.e(TAG, "upOrOpen command failure", error)
+ removeProgress()
+ Timber.tag(TAG).e("upOrOpen command failure: $error")
}
- }
+ }, TIME_OUT
+ )
+
+ }
+
+ private suspend fun sendWindowLiftCommandClick(liftPtage: Int) {
+
+ getWindowClusterForDevice().goToLiftPercentage(
+ object : ChipClusters.DefaultClusterCallback {
+ override fun onSuccess() {
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
+ Timber.tag(TAG).d("LiftPercentage command Success")
+ scope.launch {
+ readTargetPositionLift()
+ removeProgress()
+ }
+
+ }
+
+
+ override fun onError(error: Exception?) {
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
+ showMessageDialog(getString(R.string.matter_device_offline_text))
+ removeProgress()
+ Timber.tag(TAG).e("LiftPercentage command failure: $error")
+ }
+
+ }, liftPtage * 100
)
}
+ private suspend fun sendWindowTiltCommandClick(tiltPtage: Int) {
+ getWindowClusterForDevice().goToTiltPercentage(
+ object : ChipClusters.DefaultClusterCallback {
+ override fun onSuccess() {
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, true)
+ Timber.tag(TAG).d("TiltPercentage command Success")
+ scope.launch {
+ readTargetPositionTilt()
+ }
+ }
+
+
+ override fun onError(error: Exception?) {
+ SharedPrefsUtils.updateDeviceByDeviceId(mPrefs, deviceId, false)
+ showMessageDialog(getString(R.string.matter_device_offline_text))
+
+ Timber.tag(TAG).e("LiftPercentage command failure: $error")
+ }
+
+ }, tiltPtage * 100
+ )
+ }
+
private suspend fun getWindowClusterForDevice(): ChipClusters.WindowCoveringCluster {
return ChipClusters.WindowCoveringCluster(
ChipClient.getConnectedDevicePointer(requireContext(), deviceId),
@@ -288,26 +464,27 @@ class MatterWindowCoverFragment : Fragment() {
inner class WindowCoverChipControllerCallback : GenericChipDeviceListener() {
override fun onConnectDeviceComplete() {}
- override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
- Timber.tag(TAG).d( "onCommissioningComplete for nodeId $nodeId: $errorCode")
+ override fun onCommissioningComplete(nodeId: Long, errorCode: Long) {
+ Timber.tag(TAG).d("onCommissioningComplete for nodeId $nodeId: $errorCode")
//showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}
override fun onNotifyChipConnectionClosed() {
- Timber.tag(TAG).d( "onNotifyChipConnectionClosed")
+ Timber.tag(TAG).d("onNotifyChipConnectionClosed")
}
override fun onCloseBleComplete() {
- Timber.tag(TAG).d( "onCloseBleComplete")
+ Timber.tag(TAG).d("onCloseBleComplete")
}
- override fun onError(error: Throwable) {
+ override fun onError(error: Throwable?) {
super.onError(error)
- Timber.tag(TAG).d( "onError: $error")
+ Timber.tag(TAG).d("onError: $error")
}
}
+
interface CallBackHandler {
fun onBackHandler()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/manager/BluetoothManager.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/manager/BluetoothManager.kt
index b93b6904..519555be 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/manager/BluetoothManager.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/manager/BluetoothManager.kt
@@ -196,7 +196,7 @@ class BluetoothManager : BleCallback {
wrappedCallback.onCharacteristicChanged(gatt, characteristic)
}
- @SuppressLint("MissingPermission")
+ @SuppressLint("MissingPermission", "LogNotTimber")
override fun onCharacteristicRead(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/CHIPDeviceInfo.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/CHIPDeviceInfo.kt
index 89b95536..17a0aabd 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/CHIPDeviceInfo.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/CHIPDeviceInfo.kt
@@ -1,10 +1,12 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.model
-import android.os.Parcel
import android.os.Parcelable
-import chip.setuppayload.DiscoveryCapability
-import chip.setuppayload.SetupPayload
+import android.util.Log
import kotlinx.android.parcel.Parcelize
+import matter.onboardingpayload.OnboardingPayload
+import matter.onboardingpayload.OnboardingPayloadException
+import matter.onboardingpayload.OptionalQRCodeInfoType
+import timber.log.Timber
@Parcelize
data class CHIPDeviceInfo(
@@ -15,37 +17,67 @@ data class CHIPDeviceInfo(
val setupPinCode: Long = 0L,
var commissioningFlow: Int = 0,
val optionalQrCodeInfoMap: Map = mapOf(),
- val discoveryCapabilities: Set = setOf(),
+ val discoveryCapabilities: MutableSet = mutableSetOf(),
val isShortDiscriminator: Boolean = false,
+ val serialNumber: String = "",
val ipAddress: String? = null,
var networkType: String? = null,
+ val port: Int = 5540
+) : Parcelable {
+
+ fun toSetupPayload(): OnboardingPayload {
+ val onboardingPayload =
+ OnboardingPayload(
+ version,
+ vendorId,
+ productId,
+ commissioningFlow,
+ discoveryCapabilities,
+ discriminator,
+ isShortDiscriminator,
+ setupPinCode
+ )
+ if (serialNumber.isNotEmpty()) {
+ onboardingPayload.addSerialNumber(serialNumber)
+ }
+ optionalQrCodeInfoMap.forEach { (_, info) ->
+ if (info.type == OptionalQRCodeInfoType.TYPE_STRING && info.data != null) {
+ onboardingPayload.addOptionalVendorData(info.tag, info.data)
+ } else {
+ onboardingPayload.addOptionalVendorData(info.tag, info.intDataValue)
+ }
+ }
+ return onboardingPayload
+ }
- ) : Parcelable {
companion object {
+ private const val TAG = "CHIPDeviceInfo"
+
fun fromSetupPayload(
- setupPayload: SetupPayload,
+ setupPayload: OnboardingPayload,
isShortDiscriminator: Boolean = false
): CHIPDeviceInfo {
+ val serialNumber =
+ try {
+ setupPayload.getSerialNumber()
+ } catch (e: OnboardingPayloadException) {
+ Timber.tag(TAG).e(e, "serialNumber Exception: ${e.message}")
+ ""
+ }
return CHIPDeviceInfo(
setupPayload.version,
setupPayload.vendorId,
setupPayload.productId,
- setupPayload.discriminator,
+ setupPayload.getLongDiscriminatorValue(),
setupPayload.setupPinCode,
setupPayload.commissioningFlow,
- setupPayload.optionalQRCodeInfo.mapValues { (_, info) ->
- QrCodeInfo(
- info.tag,
- info.type,
- info.data,
- info.int32
- )
+ setupPayload.getAllOptionalVendorData().associate { info ->
+ info.tag to QrCodeInfo(info.tag, info.type, info.data, info.int32)
},
setupPayload.discoveryCapabilities,
- isShortDiscriminator
+ setupPayload.hasShortDiscriminator,
+ serialNumber
)
}
}
-
-
-}
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/DishWasherModel.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/DishWasherModel.kt
new file mode 100644
index 00000000..21ce0710
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/DishWasherModel.kt
@@ -0,0 +1,6 @@
+package com.siliconlabs.bledemo.features.demo.matter_demo.model
+
+object DishWasherModel {
+ var dishwasherCurrentRunningState = ""
+ var remainingTimeLeft : Long = 0
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/QrCodeInfo.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/QrCodeInfo.kt
index 1feeb081..5b9da5ec 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/QrCodeInfo.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/model/QrCodeInfo.kt
@@ -1,13 +1,13 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.model
import android.os.Parcelable
-import chip.setuppayload.OptionalQRCodeInfo
-import kotlinx.android.parcel.Parcelize
+import kotlinx.parcelize.Parcelize
+import matter.onboardingpayload.OptionalQRCodeInfoType
@Parcelize
data class QrCodeInfo(
val tag: Int,
- val type: OptionalQRCodeInfo.OptionalQRCodeInfoType,
- val data: String,
+ val type: OptionalQRCodeInfoType,
+ val data: String?,
val intDataValue: Int
-):Parcelable
+) : Parcelable
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/ChipClient.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/ChipClient.kt
index 5ae8ab66..14b8fe66 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/ChipClient.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/ChipClient.kt
@@ -1,11 +1,7 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.utils
import android.content.Context
-import android.os.Handler
-import android.os.Looper
-import android.util.Log
import android.widget.Toast
-import androidx.camera.core.impl.utils.ContextUtil.getApplicationContext
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.ControllerParams
import chip.devicecontroller.GetConnectedDeviceCallbackJni
@@ -18,9 +14,10 @@ import chip.platform.NsdManagerServiceResolver
import chip.platform.PreferencesConfigurationManager
import chip.platform.PreferencesKeyValueStoreManager
import com.siliconlabs.bledemo.features.demo.matter_demo.attestation.ExampleAttestationTrustStoreDelegate
+import kotlinx.coroutines.suspendCancellableCoroutine
+import timber.log.Timber
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
-import kotlin.coroutines.suspendCoroutine
object ChipClient {
@@ -31,10 +28,12 @@ object ChipClient {
fun getDeviceController(context: Context): ChipDeviceController {
getAndroidChipPlatform(context)
+
if (!this::chipDeviceController.isInitialized) {
chipDeviceController = ChipDeviceController(
ControllerParams.newBuilder()
.setControllerVendorId(VENDOR_ID)
+ .setEnableServerInteractions(true)
.build()
)
chipDeviceController.setAttestationTrustStoreDelegate(
@@ -51,7 +50,10 @@ object ChipClient {
AndroidBleManager(),
PreferencesKeyValueStoreManager(context),
PreferencesConfigurationManager(context),
- NsdManagerServiceResolver(context),
+ NsdManagerServiceResolver(
+ context,
+ NsdManagerServiceResolver.NsdManagerResolverAvailState()
+ ),
NsdManagerServiceBrowser(context),
ChipMdnsCallbackImpl(), DiagnosticDataProviderImpl(context)
)
@@ -63,27 +65,60 @@ object ChipClient {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
}
+ /* suspend fun getConnectedDevicePointer(context: Context, nodeId: Long): Long {
+ // TODO (#21539) This is a memory leak because we currently never call releaseConnectedDevicePointer
+ // once we are done with the returned device pointer. Memory leak was introduced since the refactor
+ // that introduced it was very large in order to fix a use after free, which was considered to be
+ // worse than the memory leak that was introduced.
+
+ return suspendCancellableCoroutine { continuation ->
+ getDeviceController(context).getConnectedDevicePointer(
+ nodeId,
+ object : GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback {
+ override fun onDeviceConnected(devicePointer: Long) {
+ Timber.tag(TAG).d("Got connected device pointer")
+ continuation.resume(devicePointer)
+ }
+
+ override fun onConnectionFailure(nodeId: Long, error: Exception) {
+ val errorMessage = "Unable to get connected device with nodeId $nodeId"
+ Timber.tag(TAG).e(error, errorMessage)
+ continuation.resumeWithException(IllegalStateException(errorMessage))
+ }
+ }
+ )
+
+ }
+ }*/
+
suspend fun getConnectedDevicePointer(context: Context, nodeId: Long): Long {
- // TODO (#21539) This is a memory leak because we currently never call releaseConnectedDevicePointer
- // once we are done with the returned device pointer. Memory leak was introduced since the refactor
- // that introduced it was very large in order to fix a use after free, which was considered to be
- // worse than the memory leak that was introduced.
- return suspendCoroutine { continuation ->
- getDeviceController(context).getConnectedDevicePointer(
- nodeId,
- object : GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback {
- override fun onDeviceConnected(devicePointer: Long) {
- Log.d(TAG, "Got connected device pointer")
- continuation.resume(devicePointer)
- }
+ return suspendCancellableCoroutine { continuation ->
+ try {
+ getDeviceController(context).getConnectedDevicePointer(
+ nodeId,
+ object : GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback {
+ override fun onDeviceConnected(devicePointer: Long) {
+ Timber.tag(TAG).d("Got connected device pointer")
+ continuation.resume(devicePointer)
+ }
- override fun onConnectionFailure(nodeId: Long, error: Exception) {
- // showMessage("Device is offline",context)
- val errorMessage = "Unable to get connected device with nodeId $nodeId"
- Log.e(TAG, errorMessage, error)
- continuation.resumeWithException(IllegalStateException(errorMessage))
+ override fun onConnectionFailure(nodeId: Long, error: Exception) {
+ val errorMessage = "Unable to get connected device with nodeId $nodeId"
+ Timber.tag(TAG).e(error, errorMessage)
+ if (continuation.isActive) {
+ continuation.resumeWithException(IllegalStateException(errorMessage))
+ }
+ // continuation.resumeWithException(IllegalStateException(errorMessage))
+ }
}
- })
+ )
+ } catch (e: Exception) {
+ val errorMessage = "Failed to initiate connection for nodeId $nodeId"
+ Timber.tag(TAG).e(e, errorMessage)
+ if (continuation.isActive) {
+ continuation.resumeWithException(e)
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/CustomInputDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/CustomInputDialog.kt
index 56e8f25f..a26ca1ac 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/CustomInputDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/CustomInputDialog.kt
@@ -66,10 +66,6 @@ class CustomInputDialog : DialogFragment() {
onOkButtonClick()
}
- if (dialog != null && dialog!!.window != null) {
- dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
- dialog!!.window!!.requestFeature(Window.FEATURE_NO_TITLE);
- }
return builder.create()
}
@@ -77,6 +73,12 @@ class CustomInputDialog : DialogFragment() {
super.onStart()
val dialog: Dialog? = dialog
if (dialog != null) {
+// if (dialog != null && dialog!!.window != null) {
+// dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+// dialog!!.window!!.requestFeature(Window.FEATURE_NO_TITLE);
+//
+// }
+ dialog.setCanceledOnTouchOutside(false)
dialog.window!!
.setLayout(
(getScreenWidth(requireActivity()) * MatterOTBRInputDialogFragment.WINDOW_SIZE).toInt(),
@@ -87,6 +89,7 @@ class CustomInputDialog : DialogFragment() {
private fun getScreenWidth(activity: Activity): Int {
val size = Point()
+
activity.windowManager.defaultDisplay.getSize(size)
return size.x
}
@@ -99,11 +102,15 @@ class CustomInputDialog : DialogFragment() {
dismiss()
} else {
if (enteredText.isEmpty()) {
- Toast.makeText(requireContext(),
- getString(R.string.please_enter_device_name), Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ requireContext(),
+ getString(R.string.please_enter_device_name), Toast.LENGTH_SHORT
+ ).show()
} else {
- Toast.makeText(requireContext(),
- getString(R.string.please_enter_valid_device_name), Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ requireContext(),
+ getString(R.string.please_enter_valid_device_name), Toast.LENGTH_SHORT
+ ).show()
}
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/CustomProgressDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/CustomProgressDialog.kt
index d8539634..baf8d60d 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/CustomProgressDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/CustomProgressDialog.kt
@@ -4,23 +4,43 @@ import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
+import android.view.View
+import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.databinding.CustomProgressDialogBinding
class CustomProgressDialog(context: Context) : Dialog(context) {
private lateinit var binding: CustomProgressDialogBinding
+ private var cancelButtonVisible: Boolean = false
+ private var cancelButtonClickListener: (() -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setCancelable(false)
setCanceledOnTouchOutside(false)
+
+ if (cancelButtonVisible) {
+ binding.customProgressBar.visibility = View.GONE
+ binding.customMessage.visibility = View.GONE
+ binding.layoutMatterCommissioning.visibility = View.VISIBLE
+ binding.btnCancel.setOnClickListener {
+ cancelButtonClickListener?.invoke()
+ }
+ } else {
+ binding.customProgressBar.visibility = View.VISIBLE
+ binding.customMessage.visibility = View.VISIBLE
+ binding.layoutMatterCommissioning.visibility = View.GONE
+ }
}
fun setMessage(message: String) {
binding = CustomProgressDialogBinding.inflate(LayoutInflater.from(context))
-
setContentView(binding.root)
-
// Now you can access views through binding
binding.customMessage.text = message
}
+
+ fun setCustomButtonVisible(visible: Boolean, clickListener: (() -> Unit)?) {
+ cancelButtonVisible = visible
+ cancelButtonClickListener = clickListener
+ }
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/DeviceIDUtil.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/DeviceIDUtil.kt
index 5341199e..f3c50937 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/DeviceIDUtil.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/DeviceIDUtil.kt
@@ -3,6 +3,9 @@ package com.siliconlabs.bledemo.features.demo.matter_demo.utils
import android.content.Context
import android.content.SharedPreferences
import com.siliconlabs.bledemo.BuildConfig
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
object DeviceIDUtil {
@@ -19,12 +22,16 @@ object DeviceIDUtil {
} else {
deviceID = DEFAULT_DEVICE_ID_PROD_ENV
}
+ val timestamp = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(Date())
val prefs = getPrefs(context)
+ val updatedDeviceID = "$deviceID$timestamp"
+ println("DeviceID :$updatedDeviceID")
+ println("DeviceID Long :${updatedDeviceID.toLong()}")
return if (prefs.contains(DEVICE_ID_PREFS_KEY)) {
- prefs.getLong(DEVICE_ID_PREFS_KEY, deviceID)
+ prefs.getLong(DEVICE_ID_PREFS_KEY, updatedDeviceID.toLong())
} else {
- prefs.edit().putLong(DEVICE_ID_PREFS_KEY, deviceID).apply()
- deviceID
+ prefs.edit().putLong(DEVICE_ID_PREFS_KEY, updatedDeviceID.toLong()).apply()
+ updatedDeviceID.toLong()
}
}
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
index 522a05e5..db25651f 100644
--- 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
@@ -8,7 +8,7 @@ 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
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/SharedPrefsUtils.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/SharedPrefsUtils.kt
index 1162fe56..25cd8c15 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/SharedPrefsUtils.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/SharedPrefsUtils.kt
@@ -1,7 +1,7 @@
package com.siliconlabs.bledemo.features.demo.matter_demo.utils
+
import android.content.SharedPreferences
import com.google.gson.Gson
-import android.content.Context
import com.google.gson.reflect.TypeToken
import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
@@ -15,7 +15,11 @@ object SharedPrefsUtils {
return myList ?: ArrayList()
}
- fun saveDevicesToPref(mPrefs: SharedPreferences, scannedDeviceList: ArrayList) {
+
+ fun saveDevicesToPref(
+ mPrefs: SharedPreferences,
+ scannedDeviceList: ArrayList
+ ) {
val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
val gson = Gson()
val json = gson.toJson(scannedDeviceList)
@@ -23,13 +27,18 @@ object SharedPrefsUtils {
prefsEditor.apply()
}
- fun updateDeviceAtIndex(mPrefs: SharedPreferences, index: Int, updatedDevice: MatterScannedResultModel) {
+ fun updateDeviceAtIndex(
+ mPrefs: SharedPreferences,
+ index: Int,
+ updatedDevice: MatterScannedResultModel
+ ) {
val existingList = retrieveSavedDevices(mPrefs)
if (index >= 0 && index < existingList.size) {
existingList[index] = updatedDevice
saveDevicesToPref(mPrefs, existingList)
}
}
+
fun updateDeviceByDeviceId(mPrefs: SharedPreferences, deviceId: Long, newValue: Boolean) {
val deviceList = retrieveSavedDevices(mPrefs)
var updated = false
@@ -46,6 +55,157 @@ object SharedPrefsUtils {
saveDevicesToPref(mPrefs, deviceList)
}
}
- const val ARG_ADDED_DEVICE_INFO_LIST = "addedDeviceInfoList"
+
+ //Total energy
+ fun saveDishwasherTotalEnergyConsumption(
+ mPrefs: SharedPreferences,
+ totalEnergyConsumed: Float
+ ) {
+ val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
+ prefsEditor.apply {
+ putFloat(TOTAL_ENERGY_DISHWASHER, totalEnergyConsumed)
+ apply()
+ }
+
+ }
+
+ fun getDishwasherTotalEnergyConsumption(mPrefs: SharedPreferences): Float {
+
+ return mPrefs.getFloat(TOTAL_ENERGY_DISHWASHER, 0f)
+ }
+
+ //average energy
+ fun saveDishwasherAverageEnergyPerCycle(
+ mPrefs: SharedPreferences,
+ averageEnergyPerCycleConsumed: Float
+ ) {
+ val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
+ prefsEditor.apply {
+ putFloat(AVERAGE_ENERGY_PER_CYCLE_DISHWASHER, averageEnergyPerCycleConsumed)
+ apply()
+ }
+
+ }
+
+ fun getDishwasherAverageEnergyPerCycle(mPrefs: SharedPreferences): Float{
+
+ return mPrefs.getFloat(AVERAGE_ENERGY_PER_CYCLE_DISHWASHER, 0f)
+ }
+
+ //inCurrent cycle
+ fun saveDishwasherInCurrentCycleEnergyConsumed(
+ mPrefs: SharedPreferences,
+ inCurrentCycleEnergyConsumed: Float
+ ) {
+ val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
+ prefsEditor.apply {
+ putFloat(DISHWASHER_IN_CURRENT_CYCLE_CONSUMED, inCurrentCycleEnergyConsumed)
+ apply()
+ }
+ }
+
+ fun getDishwasherInCurrentCycleEnergyConsumed(mPrefs: SharedPreferences): Float {
+
+ return mPrefs.getFloat(DISHWASHER_IN_CURRENT_CYCLE_CONSUMED, 0f)
+ }
+
+ //completedCycleCount
+ fun saveDishwasherCompletedCycleCount(
+ mPrefs: SharedPreferences,
+ completedCycleCount: Int
+ ) {
+ val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
+ prefsEditor.apply {
+ putInt(DISHWASHER_COMPLETED_CYCLE_COUNT, completedCycleCount)
+ apply()
+ }
+ }
+
+ fun getDishwasherCompletedCycleCount(mPrefs: SharedPreferences): Int {
+
+ return mPrefs.getInt(DISHWASHER_COMPLETED_CYCLE_COUNT, 0)
+ }
+
+
+ fun saveDishwasherTimeLeftFormatted(mPrefs: SharedPreferences, timeLeftInMillSeconds: Long) {
+ val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
+ prefsEditor.apply {
+ putLong(DISHWASHER_TOTAL_TIME_LEFT, timeLeftInMillSeconds)
+ apply()
+ }
+ }
+
+
+ fun getDishwasherTimeLeftFormatted(mPrefs: SharedPreferences): Long {
+ return mPrefs.getLong(DISHWASHER_TOTAL_TIME_LEFT, 600000)
+ }
+
+ fun saveDishwasherAppliedCycleStates(mPrefs: SharedPreferences, cycleStates: String) {
+ val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
+ prefsEditor.apply {
+ putString(
+ DISHWASHER_CYCLE_STATES,
+ cycleStates
+ )
+ apply()
+ }
+ }
+
+ fun getDishwasherAppliedCycleStates(mPrefs: SharedPreferences): String? {
+
+ return mPrefs.getString(DISHWASHER_CYCLE_STATES, null)
+ }
+
+
+ //SAVE progressBar
+ fun saveDishwasherCompletedCycleProgressBar(
+ mPrefs: SharedPreferences,
+ completedProgressBarCount: Int
+ ) {
+ val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
+ prefsEditor.apply {
+ putInt(DISHWASHER_COMPLETED_PROGRESS_BAR_COUNT, completedProgressBarCount)
+ apply()
+ }
+ }
+
+ fun getDishwasherCompletedCycleProgressBar(mPrefs: SharedPreferences): Int {
+ return mPrefs.getInt(DISHWASHER_COMPLETED_PROGRESS_BAR_COUNT, 0)
+ }
+
+ fun clearDishwasherSharedPreferences(preferences: SharedPreferences) {
+ preferences.edit().apply {
+ clear() // Clears all data in the SharedPreferences
+ apply() // Commit the changes asynchronously
+ }
+ }
+
+ fun saveTheDishwasherStateIfTheUserIsInPauseState(mPrefs: SharedPreferences, savePauseOrStopState: Boolean): Boolean {
+ val prefsEditor: SharedPreferences.Editor = mPrefs.edit()
+
+ // Save the state and apply the changes
+ prefsEditor.putBoolean(DISHWASHER_ON_CYCLE_PAUSE_RESUME_STATE, savePauseOrStopState)
+ prefsEditor.apply()
+
+ // Return true if the operation was successful (SharedPreferences doesn't give an explicit success/failure status)
+ return true
+ }
+
+ fun getDishwasherStateIfUserIsInPauseState(mPrefs: SharedPreferences): Boolean {
+ // Retrieve the state using the same key, with a default value of false if not found
+ return mPrefs.getBoolean(DISHWASHER_ON_CYCLE_PAUSE_RESUME_STATE, false)
+ }
+
+
+ const val ARG_ADDED_DEVICE_INFO_LIST = "addedDeviceInfoList"
+ const val TOTAL_ENERGY_DISHWASHER = "totalEnergyDishwasher"
+ const val AVERAGE_ENERGY_PER_CYCLE_DISHWASHER = "averageEnergyPerCycle"
+ const val DISHWASHER_IN_CURRENT_CYCLE_CONSUMED = "inCurrentCycle"
+ const val DISHWASHER_COMPLETED_CYCLE_COUNT = "cycleCount"
+ const val DISHWASHER_TOTAL_TIME_LEFT = "timeLeft"
+ const val DISHWASHER_CYCLE_STATES = "dishwasherCycleStates"
+ const val DISHWASHER_COMPLETED_PROGRESS_BAR_COUNT = "dishwasherCompletedProgressBarCount"
+ const val DISHWASHER_ON_CYCLE_PAUSE_RESUME_STATE = "dishwasherOnPauseOrStopState"
+
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/viewholder/MatterItemViewModel.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/viewholder/MatterItemViewModel.kt
index baa8dcc7..e73a1ffe 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/viewholder/MatterItemViewModel.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/viewholder/MatterItemViewModel.kt
@@ -5,16 +5,17 @@ import androidx.recyclerview.widget.RecyclerView
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.databinding.MatterScannedListItemBinding
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.CONTACT_SENSOR_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.DISHWASHER_TYPE
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.ENHANCED_COLOR_LIGHT_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.LIGHTNING_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.LOCK_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.DIMMABLE_LIGHT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.DOOR_LOCK_TYPE
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.OCCUPANCY_SENSOR_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.ONOFF_LIGHT_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.PLUG_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.TEMPERATURE_COLOR_LIGHT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.ON_OFF_LIGHT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.DIMMABLE_PLUG_IN_UNIT_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.COLOR_TEMPERATURE_LIGHT_TYPE
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.TEMPERATURE_SENSOR_TYPE
import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.THERMOSTAT_TYPE
-import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.WINDOW_TYPE
+import com.siliconlabs.bledemo.features.demo.matter_demo.fragments.MatterScannedResultFragment.Companion.WINDOW_COVERING_TYPE
import com.siliconlabs.bledemo.features.demo.matter_demo.model.MatterScannedResultModel
class MatterItemViewModel(
@@ -27,14 +28,15 @@ class MatterItemViewModel(
binding.textViewHeader.text = get.matterName
when (get.deviceType) {
- LIGHTNING_TYPE, ENHANCED_COLOR_LIGHT_TYPE, ONOFF_LIGHT_TYPE, TEMPERATURE_COLOR_LIGHT_TYPE -> binding.imageview.setImageResource(R.drawable.matter_light_list)
- THERMOSTAT_TYPE -> binding.imageview.setImageResource(R.drawable.matter_thermostat)
- WINDOW_TYPE -> binding.imageview.setImageResource(R.drawable.matter_window_close)
- LOCK_TYPE -> binding.imageview.setImageResource(R.drawable.matter_door_lock)
- OCCUPANCY_SENSOR_TYPE -> binding.imageview.setImageResource(R.drawable.matter_occupancy_sensor_list)
- CONTACT_SENSOR_TYPE -> binding.imageview.setImageResource(R.drawable.matter_contact_sensor_list)
- TEMPERATURE_SENSOR_TYPE -> binding.imageview.setImageResource(R.drawable.matter_thermometer_list)
- PLUG_TYPE -> binding.imageview.setImageResource(R.drawable.matter_plug_off)
+ DIMMABLE_LIGHT_TYPE, ENHANCED_COLOR_LIGHT_TYPE, ON_OFF_LIGHT_TYPE, COLOR_TEMPERATURE_LIGHT_TYPE -> binding.imageView.setImageResource(R.drawable.matter_light_list)
+ THERMOSTAT_TYPE -> binding.imageView.setImageResource(R.drawable.matter_thermostat)
+ WINDOW_COVERING_TYPE -> binding.imageView.setImageResource(R.drawable.matter_window_close)
+ DOOR_LOCK_TYPE -> binding.imageView.setImageResource(R.drawable.matter_door_lock)
+ OCCUPANCY_SENSOR_TYPE -> binding.imageView.setImageResource(R.drawable.matter_occupancy_sensor_list)
+ CONTACT_SENSOR_TYPE -> binding.imageView.setImageResource(R.drawable.matter_contact_sensor_list)
+ TEMPERATURE_SENSOR_TYPE -> binding.imageView.setImageResource(R.drawable.matter_thermometer_list)
+ DIMMABLE_PLUG_IN_UNIT_TYPE -> binding.imageView.setImageResource(R.drawable.matter_plug_off)
+ DISHWASHER_TYPE -> binding.imageView.setImageResource(R.drawable.matter_dishwasher_list)
else -> println("To Be Implemented...")
}
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 91eb1c00..8a431ee8 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
@@ -7,6 +7,7 @@ import android.os.Bundle
import android.os.CountDownTimer
import android.os.Handler
import android.os.Looper
+import android.view.LayoutInflater
import android.view.MenuItem
import android.view.WindowManager
import android.widget.TextView
@@ -16,6 +17,7 @@ import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.activities.BaseDemoActivity
import com.siliconlabs.bledemo.bluetooth.ble.*
import com.siliconlabs.bledemo.bluetooth.services.BluetoothService
+import com.siliconlabs.bledemo.databinding.ActivityRangeTestBinding
import com.siliconlabs.bledemo.features.demo.range_test.dialogs.RangeTestModeDialog
import com.siliconlabs.bledemo.features.demo.range_test.fragments.RangeTestFragment
import com.siliconlabs.bledemo.features.demo.range_test.models.*
@@ -25,7 +27,6 @@ import com.siliconlabs.bledemo.features.demo.range_test.presenters.RangeTestPres
import com.siliconlabs.bledemo.home_screen.dialogs.SelectDeviceDialog
import com.siliconlabs.bledemo.utils.BLEUtils.setNotificationForCharacteristic
import com.siliconlabs.bledemo.utils.Notifications
-import kotlinx.android.synthetic.main.activity_range_test.*
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.util.*
@@ -39,7 +40,7 @@ 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
@@ -53,7 +54,7 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
private var timerStarted = false
private var retryAttempts = 0
-
+ private lateinit var binding: ActivityRangeTestBinding
private var txUpdateTimer: TxUpdateTimer? = null
@@ -125,23 +126,26 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_range_test)
+ binding = ActivityRangeTestBinding.inflate(LayoutInflater.from(baseContext))
+ setContentView(binding.root)
+ //setContentView(R.layout.activity_range_test)
setupUiListeners()
}
private fun setupUiListeners() {
- tv_device1_tab.setOnClickListener {
- changeDevice(tv_device1_tab, 1)
+
+ binding.tvDevice1Tab.setOnClickListener {
+ changeDevice(binding.tvDevice1Tab, 1)
}
- tv_device2_tab.setOnClickListener {
- changeDevice(tv_device2_tab, 2)
+ binding.tvDevice2Tab.setOnClickListener {
+ changeDevice(binding.tvDevice2Tab, 2)
}
}
override fun onBluetoothServiceBound() {
- selectTab(tv_device1_tab)
- changeDevice(tv_device1_tab, 1)
+ selectTab(binding.tvDevice1Tab)
+ changeDevice(binding.tvDevice1Tab, 1)
}
@@ -191,8 +195,8 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
}
})
}.also {
- it.show(supportFragmentManager, "select_device_dialog")
- }
+ it.show(supportFragmentManager, "select_device_dialog")
+ }
} else {
showRangeTestFragment(presenter.getMode())
}
@@ -567,11 +571,11 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
presenter.resetDeviceAt(resetDeviceId)
if (resetDeviceId == 1) {
- tv_device1_tab.text = getString(R.string.range_test_no_device)
- changeDevice(tv_device1_tab, 1)
+ binding.tvDevice1Tab.text = getString(R.string.range_test_no_device)
+ changeDevice(binding.tvDevice1Tab, 1)
} else {
- tv_device2_tab.text = getString(R.string.range_test_no_device)
- changeDevice(tv_device2_tab, 2)
+ binding.tvDevice2Tab.text = getString(R.string.range_test_no_device)
+ changeDevice(binding.tvDevice2Tab, 2)
}
}
}
@@ -785,9 +789,9 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
) {
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()
@@ -806,9 +810,8 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
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) }
@@ -828,16 +831,18 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
if (descriptor?.uuid == UUID.fromString("00002906-0000-1000-8000-00805f9b34fb")) {
try {
val validRangeValue = descriptor.value
- lowerLimit = (validRangeValue[1].toInt() and 0xFF) shl 8 or (validRangeValue[0].toInt() and 0xFF)
- upperLimit = (validRangeValue[3].toInt() and 0xFF) shl 8 or (validRangeValue[2].toInt() and 0xFF)
+ lowerLimit =
+ (validRangeValue[1].toInt() and 0xFF) shl 8 or (validRangeValue[0].toInt() and 0xFF)
+ upperLimit =
+ (validRangeValue[3].toInt() and 0xFF) shl 8 or (validRangeValue[2].toInt() and 0xFF)
RangeTestValues.setChannelsMinMax(lowerLimit, upperLimit)
- val gattCharacteristic1 = GattCharacteristic.fromUuid(descriptor.characteristic.uuid)
+ val gattCharacteristic1 =
+ GattCharacteristic.fromUuid(descriptor.characteristic.uuid)
gattCharacteristic1?.let {
updatePresenter(gatt, descriptor, it)
}
- }catch (e:Exception)
- {
+ } catch (e: Exception) {
e.stackTrace
}
}
@@ -1221,8 +1226,8 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
}
private fun selectTab(tvTab: TextView) {
- setTabUnselected(tv_device1_tab)
- setTabUnselected(tv_device2_tab)
+ setTabUnselected(binding.tvDevice1Tab)
+ setTabUnselected(binding.tvDevice2Tab)
setTabSelected(tvTab)
}
@@ -1244,7 +1249,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
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/dialogs/RangeTestModeDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/dialogs/RangeTestModeDialog.kt
index b14a8594..4d523ac6 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/dialogs/RangeTestModeDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/dialogs/RangeTestModeDialog.kt
@@ -9,12 +9,12 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
+import com.siliconlabs.bledemo.databinding.DialogRangeTestModeBinding
import com.siliconlabs.bledemo.features.demo.range_test.activities.RangeTestActivity
import com.siliconlabs.bledemo.features.demo.range_test.models.RangeTestMode
import com.siliconlabs.bledemo.features.demo.range_test.models.TxPower
import com.siliconlabs.bledemo.features.demo.range_test.presenters.RangeTestPresenter.Controller
import com.siliconlabs.bledemo.features.demo.range_test.presenters.RangeTestPresenter.RangeTestView
-import kotlinx.android.synthetic.main.dialog_range_test_mode.*
import java.text.DecimalFormat
import java.util.*
@@ -22,10 +22,11 @@ import java.util.*
* @author Comarch S.A.
*/
class RangeTestModeDialog : BaseDialogFragment(
- hasCustomWidth = true,
- isCanceledOnTouchOutside = false
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = false
), RangeTestView {
lateinit var controller: Controller
+ private lateinit var binding: DialogRangeTestModeBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return object : Dialog(requireContext(), theme) {
@@ -44,8 +45,13 @@ class RangeTestModeDialog : BaseDialogFragment(
setStyle(STYLE_NO_TITLE, theme)
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_range_test_mode, container, false)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogRangeTestModeBinding.inflate(inflater, container, false)
+ return binding.root
}
@@ -54,16 +60,13 @@ class RangeTestModeDialog : BaseDialogFragment(
controller = activity as RangeTestActivity
controller.setView(this)
-
- tx_mode.setOnClickListener {
+ binding.txMode.setOnClickListener {
onTxModeButtonClicked()
}
-
- rx_mode.setOnClickListener {
+ binding.rxMode.setOnClickListener {
onRxModeButtonClicked()
}
-
- btn_cancel.setOnClickListener {
+ binding.btnCancel.setOnClickListener {
onCancelButtonClicked()
}
@@ -92,17 +95,17 @@ class RangeTestModeDialog : BaseDialogFragment(
}
override fun showDeviceName(name: String?) {
- tv_device_name.text = name
+ binding.tvDeviceName.text = name
}
override fun showModelNumber(number: String?, running: Boolean?) {
- tv_device_number.text = number
+ binding.tvDeviceNumber .text = number
}
override fun showTxPower(power: TxPower?, values: List) {
val value = power?.asDisplayValue()
val formatter = DecimalFormat("#.##")
- tv_tx_power.text = String.format(Locale.ROOT, "%sdBm", formatter.format(value?.toDouble()))
+ binding.tvTxPower.text = String.format(Locale.ROOT, "%sdBm", formatter.format(value?.toDouble()))
}
override fun showPayloadLength(length: Int, values: List) {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/fragments/RangeTestFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/fragments/RangeTestFragment.kt
index f9e1513f..c09649d1 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/fragments/RangeTestFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/fragments/RangeTestFragment.kt
@@ -25,13 +25,13 @@ import com.github.mikephil.charting.utils.Transformer
import com.github.mikephil.charting.utils.Utils
import com.github.mikephil.charting.utils.ViewPortHandler
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.FragmentRangeTestBinding
import com.siliconlabs.bledemo.features.demo.range_test.activities.RangeTestActivity
import com.siliconlabs.bledemo.features.demo.range_test.models.RangeTestMode
import com.siliconlabs.bledemo.features.demo.range_test.models.RangeTestValues
import com.siliconlabs.bledemo.features.demo.range_test.models.TxPower
import com.siliconlabs.bledemo.features.demo.range_test.presenters.RangeTestPresenter
import com.siliconlabs.bledemo.features.demo.range_test.presenters.RangeTestPresenter.Controller
-import kotlinx.android.synthetic.main.fragment_range_test.*
import java.util.*
import java.util.regex.Pattern
@@ -59,6 +59,7 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
private var txLayouts: ArrayList = ArrayList()
private var rxLayouts: ArrayList = ArrayList()
private var disabledLayouts: ArrayList = ArrayList()
+ private lateinit var binding: FragmentRangeTestBinding
override fun onCreate(savedInstanceState: Bundle?) {
@@ -70,60 +71,66 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.fragment_range_test, container, false)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentRangeTestBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
txLayouts.apply {
- add(range_transmitted_layout)
- add(tv_range_tx_power_layout_1)
- add(range_tx_power_layout_2)
+ add(binding.rangeTransmittedLayout)
+ add(binding.tvRangeTxPowerLayout1)
+ add(binding.rangeTxPowerLayout2)
}
rxLayouts.apply {
- add(range_rx_data_row_1)
- add(range_rx_data_row_2)
- add(chart)
- add(tv_range_rx_chart_label)
+ add(binding.rangeRxDataRow1)
+ add(binding.rangeRxDataRow2)
+ add(binding.chart)
+ add(binding.tvRangeRxChartLabel)
}
disabledLayouts.apply {
- add(sb_range_tx_power)
- add(sb_range_payload_length)
- add(range_seek_ma_window_size)
- add(sp_tx_power)
- add(sp_payload_length)
- add(sp_ma_window_size)
- add(sp_remote_id)
- add(sp_self_id)
- add(range_check_uart_log)
- add(range_check_packet_repeat)
- add(sp_phy_config)
+ add(binding.sbRangeTxPower)
+ add(binding.sbRangePayloadLength)
+ add(binding.rangeSeekMaWindowSize)
+ add(binding.spTxPower)
+ add(binding.spPayloadLength)
+ add(binding.spMaWindowSize)
+ add(binding.spRemoteId)
+ add(binding.spSelfId)
+ add(binding.rangeCheckUartLog)
+ add(binding.rangeCheckPacketRepeat)
+ add(binding.spPhyConfig)
}
mode?.let { setup(it) }
controller.setView(this)
- range_test_start_stop.setOnClickListener {
+ binding.rangeTestStartStop.setOnClickListener {
controller.toggleRunningState()
}
- range_check_packet_repeat.setOnCheckedChangeListener { _, checked ->
- sp_packet_count.isEnabled = !checked
+ binding.rangeCheckPacketRepeat.setOnCheckedChangeListener { _, checked ->
+
+ binding.spPacketCount.isEnabled = !checked
if (checked) {
controller.updatePacketCount(RangeTestValues.PACKET_COUNT_REPEAT)
} else {
- val packetCountIndex = sp_packet_count.selectedItemPosition
+ val packetCountIndex = binding.spPacketCount.selectedItemPosition
val packetCount = RangeTestValues.PACKET_COUNT_LOOKUP[packetCountIndex]
controller.updatePacketCount(packetCount)
}
}
- range_check_uart_log.setOnCheckedChangeListener { _, checked ->
+ binding.rangeCheckUartLog.setOnCheckedChangeListener { _, checked ->
controller.updateUartLogEnabled(checked)
}
@@ -136,7 +143,7 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
}
private fun clearChart() {
- if (chart == null || chartDataSet == null) {
+ if (binding.chart == null || chartDataSet == null) {
return
}
@@ -148,8 +155,8 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
}
chartData?.notifyDataChanged()
- chart.notifyDataSetChanged()
- chart.invalidate()
+ binding.chart.notifyDataSetChanged()
+ binding.chart.invalidate()
}
override fun runOnUiThread(runnable: Runnable?) {
@@ -157,75 +164,79 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
}
override fun showDeviceName(name: String?) {
- tv_range_device_name.text = name
+ binding.tvRangeDeviceName.text = name
}
override fun showModelNumber(number: String?, running: Boolean?) {
- tv_range_model_number.text = number
+ binding.tvRangeModelNumber.text = number
val pattern = Pattern.compile(SERIES_2_REGEX, Pattern.CASE_INSENSITIVE)
series1 = !pattern.matcher(number).find()
- if (running != null && running) sp_channel_number.isEnabled = false
- else sp_channel_number.isEnabled = series1
+
+ if (running != null && running) binding.spChannelNumber.isEnabled = false
+ else binding.spChannelNumber.isEnabled = series1
}
override fun showTxPower(power: TxPower?, values: List) {
if (values != txPowerValues) {
- setupSpinnerValues(sp_tx_power, values)
- sb_range_tx_power.max = values.size - 1
- sb_range_tx_power.setOnSeekBarChangeListener(seekBarsListener)
- sp_tx_power.onItemSelectedListener = SpinnerSeekBarListener(sb_range_tx_power)
+ setupSpinnerValues(binding.spTxPower, values)
+ binding.sbRangeTxPower.max = values.size - 1
+ binding.sbRangeTxPower.setOnSeekBarChangeListener(seekBarsListener)
+ binding.spTxPower.onItemSelectedListener =
+ SpinnerSeekBarListener(binding.sbRangeTxPower)
txPowerValues = values
}
val index = values.indexOf(power)
if (index != -1) {
- sb_range_tx_power.progress = index
- sp_tx_power.setSelection(index)
+ binding.sbRangeTxPower.progress = index
+ binding.spTxPower.setSelection(index)
}
}
override fun showPayloadLength(length: Int, values: List) {
if (values != payloadLengthValues) {
- setupSpinnerValues(sp_payload_length, values)
- sb_range_payload_length.max = values.size - 1
- sb_range_payload_length.setOnSeekBarChangeListener(seekBarsListener)
- sp_payload_length.onItemSelectedListener = SpinnerSeekBarListener(sb_range_payload_length)
+ setupSpinnerValues(binding.spPayloadLength, values)
+ binding.sbRangePayloadLength.max = values.size - 1
+ binding.sbRangePayloadLength.setOnSeekBarChangeListener(seekBarsListener)
+ binding.spPayloadLength.onItemSelectedListener =
+ SpinnerSeekBarListener(binding.sbRangePayloadLength)
payloadLengthValues = values
}
val index = values.indexOf(length)
if (index != -1) {
- sb_range_payload_length.progress = index
- sp_payload_length.setSelection(index)
+ binding.sbRangePayloadLength.progress = index
+ binding.spPayloadLength.setSelection(index)
}
}
override fun showMaWindowSize(size: Int, values: List) {
if (values != maWindowSizeValues) {
- setupSpinnerValues(sp_ma_window_size, values)
- range_seek_ma_window_size.max = values.size - 1
- range_seek_ma_window_size.setOnSeekBarChangeListener(seekBarsListener)
- sp_ma_window_size.onItemSelectedListener = SpinnerSeekBarListener(range_seek_ma_window_size)
+ setupSpinnerValues(binding.spMaWindowSize, values)
+ binding.rangeSeekMaWindowSize.max = values.size - 1
+ binding.rangeSeekMaWindowSize.setOnSeekBarChangeListener(seekBarsListener)
+ binding.spMaWindowSize.onItemSelectedListener =
+ SpinnerSeekBarListener(binding.rangeSeekMaWindowSize)
maWindowSizeValues = values
}
val index = values.indexOf(size)
if (index != -1) {
- range_seek_ma_window_size.progress = index
- sp_ma_window_size.setSelection(index)
+ binding.rangeSeekMaWindowSize.progress = index
+ binding.spMaWindowSize.setSelection(index)
}
}
override fun showChannelNumber(number: Int) {
val index = RangeTestValues.CHANNEL_LOOKUP.indexOf(number)
- sp_channel_number.setSelection(index)
+ binding.spChannelNumber.setSelection(index)
}
override fun showPacketCountRepeat(enabled: Boolean) {
- range_check_packet_repeat.isChecked = enabled
+ binding.rangeCheckPacketRepeat.isChecked = enabled
}
override fun showPacketRequired(required: Int) {
val index = RangeTestValues.PACKET_COUNT_LOOKUP.indexOf(required)
- sp_packet_count.setSelection(index)
+ binding.spPacketCount.setSelection(index)
}
override fun showPacketSent(sent: Int) {
@@ -242,16 +253,16 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
override fun showRemoteId(id: Int) {
val index = RangeTestValues.ID_LOOKUP.indexOf(id)
- sp_remote_id.setSelection(index)
+ binding.spRemoteId.setSelection(index)
}
override fun showSelfId(id: Int) {
val index = RangeTestValues.ID_LOOKUP.indexOf(id)
- sp_self_id.setSelection(index)
+ binding.spSelfId.setSelection(index)
}
override fun showUartLogEnabled(enabled: Boolean) {
- range_check_uart_log.isChecked = enabled
+ binding.rangeCheckUartLog.isChecked = enabled
}
override fun showRunningState(running: Boolean) {
@@ -272,16 +283,17 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
return
}
- val valuesList: List> = ArrayList>(values.entries)
+ val valuesList: List> =
+ ArrayList>(values.entries)
if (valuesList != phyValues) {
- setupSpinnerValues(sp_phy_config, ArrayList(values.values))
+ setupSpinnerValues(binding.spPhyConfig, ArrayList(values.values))
phyValues = valuesList
}
for (i in valuesList.indices) {
val entry = valuesList[i]
if (entry.key == phy) {
- sp_phy_config.setSelection(i)
+ binding.spPhyConfig.setSelection(i)
return
}
}
@@ -296,7 +308,7 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
seekBarsListener = SeekBarsListener()
if (mode == RangeTestMode.Tx) {
setVisibility(rxLayouts, View.GONE)
- setupSpinnerValues(sp_tx_power, listOf(""))
+ setupSpinnerValues(binding.spTxPower, listOf(""))
buttonStringIdOff = R.string.range_tx_start
buttonStringIdOn = R.string.range_tx_stop
setPacketSent(0)
@@ -311,93 +323,96 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
setPer(0f)
}
- setupSpinnerValues(sp_payload_length, listOf(""))
- setupSpinnerValues(sp_ma_window_size, listOf(""))
- setupSpinnerValues(sp_channel_number, RangeTestValues.CHANNEL_LOOKUP)
- setupSpinnerValues(sp_packet_count, RangeTestValues.PACKET_COUNT_LOOKUP)
- setupSpinnerValues(sp_remote_id, RangeTestValues.ID_LOOKUP)
- setupSpinnerValues(sp_self_id, RangeTestValues.ID_LOOKUP)
+ setupSpinnerValues(binding.spPayloadLength, listOf(""))
+ setupSpinnerValues(binding.spMaWindowSize, listOf(""))
+ setupSpinnerValues(binding.spChannelNumber, RangeTestValues.CHANNEL_LOOKUP)
+ setupSpinnerValues(binding.spPacketCount, RangeTestValues.PACKET_COUNT_LOOKUP)
+ setupSpinnerValues(binding.spRemoteId, RangeTestValues.ID_LOOKUP)
+ setupSpinnerValues(binding.spSelfId, RangeTestValues.ID_LOOKUP)
- sp_channel_number.onItemSelectedListener = object : SpinnerListener() {
+ binding.spChannelNumber.onItemSelectedListener = object : SpinnerListener() {
override fun onItemSelected(index: Int) {
val channel = RangeTestValues.CHANNEL_LOOKUP[index]
controller.updateChannel(channel)
}
}
- sp_packet_count.onItemSelectedListener = object : SpinnerListener() {
+ binding.spPacketCount.onItemSelectedListener = object : SpinnerListener() {
override fun onItemSelected(index: Int) {
val packetCount = RangeTestValues.PACKET_COUNT_LOOKUP[index]
controller.updatePacketCount(packetCount)
}
}
- sp_remote_id.onItemSelectedListener = object : SpinnerListener() {
+ binding.spRemoteId.onItemSelectedListener = object : SpinnerListener() {
override fun onItemSelected(index: Int) {
val id = RangeTestValues.ID_LOOKUP[index]
controller.updateRemoteId(id)
}
}
- sp_self_id.onItemSelectedListener = object : SpinnerListener() {
+ binding.spSelfId.onItemSelectedListener = object : SpinnerListener() {
override fun onItemSelected(index: Int) {
val id = RangeTestValues.ID_LOOKUP[index]
controller.updateSelfId(id)
}
}
- sp_phy_config.onItemSelectedListener = object : SpinnerListener() {
+ binding.spPhyConfig.onItemSelectedListener = object : SpinnerListener() {
override fun onItemSelected(index: Int) {
val id = phyValues!![index].key
controller.updatePhyConfig(id)
}
}
- sb_range_tx_power.isEnabled = false
- sp_tx_power.isEnabled = false
- sb_range_payload_length.isEnabled = false
- sp_payload_length.isEnabled = false
- range_seek_ma_window_size.isEnabled = false
- sp_ma_window_size.isEnabled = false
- sp_phy_config.isEnabled = false
+ binding.sbRangeTxPower.isEnabled = false
+ binding.spTxPower.isEnabled = false
+ binding.sbRangePayloadLength.isEnabled = false
+ binding.spPayloadLength.isEnabled = false
+ binding.rangeSeekMaWindowSize.isEnabled = false
+ binding.spMaWindowSize.isEnabled = false
+ binding.spPhyConfig.isEnabled = false
setupRunning(false)
}
private fun appendChartData(rssi: Float) {
- if (chart == null || chartDataSet == null) {
+ if (binding.chart == null || chartDataSet == null) {
return
}
val index = chartDataSet!!.entryCount
chartDataSet!!.addEntry(Entry(index.toFloat(), rssi))
- chart.xAxis.axisMinimum = 0f
- chart.xAxis.axisMaximum = Math.max(50, index).toFloat()
- chart.setVisibleXRange(50f, 50f)
- chart.moveViewToX(index.toFloat())
+ binding.chart.xAxis.axisMinimum = 0f
+ binding.chart.xAxis.axisMaximum = Math.max(50, index).toFloat()
+ binding.chart.setVisibleXRange(50f, 50f)
+ binding.chart.moveViewToX(index.toFloat())
chartDataSet?.notifyDataSetChanged()
chartData?.notifyDataChanged()
- chart.notifyDataSetChanged()
- chart.invalidate()
+ binding.chart.notifyDataSetChanged()
+ binding.chart.invalidate()
}
private fun setPacketSent(packetSent: Int) {
- tv_range_test_packet_count.text = packetSent.toString()
+ binding.tvRangeTestPacketCount.text = packetSent.toString()
}
private fun setRx(received: Int, required: Int) {
- setValue(tv_range_test_rx, R.string.range_rx_rx, received, required)
+
+ setValue(binding.tvRangeTestRx, R.string.range_rx_rx, received, required)
}
private fun setRssi(rssi: Int) {
- setValue(tv_range_test_rssi, R.string.range_rx_rssi, rssi)
+
+ setValue(binding.tvRangeTestRssi, R.string.range_rx_rssi, rssi)
}
private fun setMa(ma: Float) {
- tv_range_test_ma.text = String.format(Locale.US,"%.1f",ma).plus("%")
+
+ binding.tvRangeTestMa.text = String.format(Locale.US, "%.1f", ma).plus("%")
}
private fun setPer(per: Float) {
- tv_range_test_ma.text = String.format(Locale.US,"%.1f",per).plus("%")
+ binding.tvRangeTestMa.text = String.format(Locale.US, "%.1f", per).plus("%")
}
private fun setValue(view: TextView, resId: Int, vararg args: Any) {
@@ -407,15 +422,17 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
private fun updateControllerFromSeekBar(seekBar: SeekBar) {
val progress = seekBar.progress
when {
- seekBar === sb_range_tx_power -> {
+ seekBar === binding.sbRangeTxPower -> {
val power = txPowerValues!![progress]
controller.updateTxPower(power.asCharacteristicValue())
}
- seekBar === sb_range_payload_length -> {
+
+ seekBar === binding.sbRangePayloadLength -> {
val payloadLength = payloadLengthValues!![progress]
controller.updatePayloadLength(payloadLength)
}
- seekBar === range_seek_ma_window_size -> {
+
+ seekBar === binding.rangeSeekMaWindowSize -> {
val maWindowSize = maWindowSizeValues!![progress]
controller.updateMaWindowSize(maWindowSize)
}
@@ -425,16 +442,16 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
private fun setupRunning(running: Boolean) {
if (running) {
setEnabled(disabledLayouts, false)
- sp_channel_number.isEnabled = false
- sp_packet_count.isEnabled = false
- range_test_start_stop.setText(buttonStringIdOn)
- range_test_start_stop.isEnabled = mode != RangeTestMode.Rx
+ binding.spChannelNumber.isEnabled = false
+ binding.spPacketCount.isEnabled = false
+ binding.rangeTestStartStop.setText(buttonStringIdOn)
+ binding.rangeTestStartStop.isEnabled = mode != RangeTestMode.Rx
} else {
setEnabled(disabledLayouts, true)
- sp_channel_number.isEnabled = series1
- sp_packet_count.isEnabled = !range_check_packet_repeat.isChecked
- range_test_start_stop.setText(buttonStringIdOff)
- range_test_start_stop.isEnabled = true
+ binding.spChannelNumber.isEnabled = series1
+ binding.spPacketCount.isEnabled = !binding.rangeCheckPacketRepeat.isChecked
+ binding.rangeTestStartStop.setText(buttonStringIdOff)
+ binding.rangeTestStartStop.isEnabled = true
}
}
@@ -462,7 +479,7 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
val axisColor = ContextCompat.getColor(requireContext(), R.color.silabs_dark_gray_text)
val graphColor = ContextCompat.getColor(requireContext(), R.color.silabs_blue)
- chart.apply {
+ binding.chart.apply {
description?.isEnabled = false
legend?.isEnabled = false
setScaleEnabled(false)
@@ -480,7 +497,11 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
axisLeft.setDrawAxisLine(true)
axisLeft.axisLineWidth = 0.5f
axisLeft.axisLineColor = axisColor
- rendererLeftYAxis = YAxisArrowRenderer(chart.viewPortHandler, chart.axisLeft, chart.rendererLeftYAxis.transformer)
+ rendererLeftYAxis = YAxisArrowRenderer(
+ binding.chart.viewPortHandler,
+ binding.chart.axisLeft,
+ binding.chart.rendererLeftYAxis.transformer
+ )
xAxis.setDrawGridLines(false)
xAxis.setDrawAxisLine(false)
xAxis.axisMinimum = 0f
@@ -497,11 +518,11 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
}
val chartData = createChartData(graphColor)
- chart.data = chartData
+ binding.chart.data = chartData
chartDataSet!!.notifyDataSetChanged()
chartData.notifyDataChanged()
- chart.notifyDataSetChanged()
- chart.invalidate()
+ binding.chart.notifyDataSetChanged()
+ binding.chart.invalidate()
}
private fun createChartData(color: Int): LineData {
@@ -550,14 +571,16 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
when {
- seekBar === sb_range_tx_power -> {
- sp_tx_power.setSelection(progress)
+ seekBar === binding.sbRangeTxPower -> {
+ binding.spTxPower.setSelection(progress)
}
- seekBar === sb_range_payload_length -> {
- sp_payload_length.setSelection(progress)
+
+ seekBar === binding.sbRangePayloadLength -> {
+ binding.spPayloadLength.setSelection(progress)
}
- seekBar === range_seek_ma_window_size -> {
- sp_ma_window_size.setSelection(progress)
+
+ seekBar === binding.rangeSeekMaWindowSize -> {
+ binding.spMaWindowSize.setSelection(progress)
}
}
}
@@ -569,7 +592,8 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
}
}
- private inner class SpinnerSeekBarListener(private val seekBar: SeekBar) : AdapterView.OnItemSelectedListener {
+ private inner class SpinnerSeekBarListener(private val seekBar: SeekBar) :
+ AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
seekBar.progress = position
updateControllerFromSeekBar(seekBar)
@@ -601,12 +625,19 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
}
private inner class CubicLineSampleFillFormatter : IFillFormatter {
- override fun getFillLinePosition(dataSet: ILineDataSet, dataProvider: LineDataProvider): Float {
+ override fun getFillLinePosition(
+ dataSet: ILineDataSet,
+ dataProvider: LineDataProvider
+ ): Float {
return (-100).toFloat()
}
}
- private class YAxisArrowRenderer(viewPortHandler: ViewPortHandler, yAxis: YAxis, trans: Transformer) : YAxisRenderer(viewPortHandler, yAxis, trans) {
+ private class YAxisArrowRenderer(
+ viewPortHandler: ViewPortHandler,
+ yAxis: YAxis,
+ trans: Transformer
+ ) : YAxisRenderer(viewPortHandler, yAxis, trans) {
private val ARROW_SIZE = Utils.convertDpToPixel(3.5f)
private val arrowPath = Path()
private val arrowPaint = Paint(Paint.ANTI_ALIAS_FLAG)
@@ -622,18 +653,46 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
arrowPaint.color = mYAxis.axisLineColor
arrowPath.reset()
if (mYAxis.axisDependency == YAxis.AxisDependency.LEFT) {
- c.drawLine(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop() - ARROW_SIZE * 1.5f, mViewPortHandler.contentLeft(),
- mViewPortHandler.contentBottom(), mAxisLinePaint)
- arrowPath.moveTo(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop() - ARROW_SIZE * 1.5f)
- arrowPath.lineTo(mViewPortHandler.contentLeft() + ARROW_SIZE / 2f, mViewPortHandler.contentTop() - ARROW_SIZE * 0.5f)
- arrowPath.lineTo(mViewPortHandler.contentLeft() - ARROW_SIZE / 2f, mViewPortHandler.contentTop() - ARROW_SIZE * 0.5f)
+ c.drawLine(
+ mViewPortHandler.contentLeft(),
+ mViewPortHandler.contentTop() - ARROW_SIZE * 1.5f,
+ mViewPortHandler.contentLeft(),
+ mViewPortHandler.contentBottom(),
+ mAxisLinePaint
+ )
+ arrowPath.moveTo(
+ mViewPortHandler.contentLeft(),
+ mViewPortHandler.contentTop() - ARROW_SIZE * 1.5f
+ )
+ arrowPath.lineTo(
+ mViewPortHandler.contentLeft() + ARROW_SIZE / 2f,
+ mViewPortHandler.contentTop() - ARROW_SIZE * 0.5f
+ )
+ arrowPath.lineTo(
+ mViewPortHandler.contentLeft() - ARROW_SIZE / 2f,
+ mViewPortHandler.contentTop() - ARROW_SIZE * 0.5f
+ )
arrowPath.close()
} else {
- c.drawLine(mViewPortHandler.contentRight(), mViewPortHandler.contentTop() - ARROW_SIZE * 1.5f, mViewPortHandler.contentRight(),
- mViewPortHandler.contentBottom(), mAxisLinePaint)
- arrowPath.moveTo(mViewPortHandler.contentRight(), mViewPortHandler.contentTop() - ARROW_SIZE * 1.5f)
- arrowPath.lineTo(mViewPortHandler.contentRight() + ARROW_SIZE / 2f, mViewPortHandler.contentTop() - ARROW_SIZE * 0.5f)
- arrowPath.lineTo(mViewPortHandler.contentRight() - ARROW_SIZE / 2f, mViewPortHandler.contentTop() - ARROW_SIZE * 0.5f)
+ c.drawLine(
+ mViewPortHandler.contentRight(),
+ mViewPortHandler.contentTop() - ARROW_SIZE * 1.5f,
+ mViewPortHandler.contentRight(),
+ mViewPortHandler.contentBottom(),
+ mAxisLinePaint
+ )
+ arrowPath.moveTo(
+ mViewPortHandler.contentRight(),
+ mViewPortHandler.contentTop() - ARROW_SIZE * 1.5f
+ )
+ arrowPath.lineTo(
+ mViewPortHandler.contentRight() + ARROW_SIZE / 2f,
+ mViewPortHandler.contentTop() - ARROW_SIZE * 0.5f
+ )
+ arrowPath.lineTo(
+ mViewPortHandler.contentRight() - ARROW_SIZE / 2f,
+ mViewPortHandler.contentTop() - ARROW_SIZE * 0.5f
+ )
arrowPath.close()
}
c.drawPath(arrowPath, arrowPaint)
@@ -669,8 +728,14 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
arrowPaint.color = l.getLineColor()
arrowPath.reset()
arrowPath.moveTo(mViewPortHandler.contentRight(), pts[1])
- arrowPath.lineTo(mViewPortHandler.contentRight() - ARROW_SIZE, pts[1] + ARROW_SIZE / 2f)
- arrowPath.lineTo(mViewPortHandler.contentRight() - ARROW_SIZE, pts[1] - ARROW_SIZE / 2f)
+ arrowPath.lineTo(
+ mViewPortHandler.contentRight() - ARROW_SIZE,
+ pts[1] + ARROW_SIZE / 2f
+ )
+ arrowPath.lineTo(
+ mViewPortHandler.contentRight() - ARROW_SIZE,
+ pts[1] - ARROW_SIZE / 2f
+ )
arrowPath.close()
c.drawPath(arrowPath, arrowPaint)
}
@@ -690,24 +755,32 @@ class RangeTestFragment : Fragment(), RangeTestPresenter.RangeTestView {
val position = l.labelPosition
if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) {
mLimitLinePaint.textAlign = Paint.Align.RIGHT
- c.drawText(label,
- mViewPortHandler.contentRight() - xOffset,
- pts[1] - yOffset + labelLineHeight, mLimitLinePaint)
+ c.drawText(
+ label,
+ mViewPortHandler.contentRight() - xOffset,
+ pts[1] - yOffset + labelLineHeight, mLimitLinePaint
+ )
} else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) {
mLimitLinePaint.textAlign = Paint.Align.RIGHT
- c.drawText(label,
- mViewPortHandler.contentRight() - xOffset,
- pts[1] + yOffset, mLimitLinePaint)
+ c.drawText(
+ label,
+ mViewPortHandler.contentRight() - xOffset,
+ pts[1] + yOffset, mLimitLinePaint
+ )
} else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) {
mLimitLinePaint.textAlign = Paint.Align.LEFT
- c.drawText(label,
- mViewPortHandler.contentLeft() + xOffset,
- pts[1] - yOffset + labelLineHeight, mLimitLinePaint)
+ c.drawText(
+ label,
+ mViewPortHandler.contentLeft() + xOffset,
+ pts[1] - yOffset + labelLineHeight, mLimitLinePaint
+ )
} else {
mLimitLinePaint.textAlign = Paint.Align.LEFT
- c.drawText(label,
- mViewPortHandler.offsetLeft() + xOffset,
- pts[1] + yOffset, mLimitLinePaint)
+ c.drawText(
+ label,
+ mViewPortHandler.offsetLeft() + xOffset,
+ pts[1] + yOffset, mLimitLinePaint
+ )
}
}
c.restoreToCount(clipRestoreCount)
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/activities/ThunderboardActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/activities/ThunderboardActivity.kt
index 7bdf1cd6..1d53e25b 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/activities/ThunderboardActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/activities/ThunderboardActivity.kt
@@ -3,17 +3,20 @@ package com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.activities
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothProfile
import android.os.Bundle
+import android.view.LayoutInflater
import android.widget.FrameLayout
+import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.base.activities.BaseDemoActivity
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.databinding.ActivityThunderboardBaseBinding
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.fragments.StatusFragment
-import com.siliconlabs.bledemo.base.activities.BaseDemoActivity
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.models.ThunderBoardDevice
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.utils.SensorChecker
import com.siliconlabs.bledemo.utils.GattQueue
-import kotlinx.android.synthetic.main.activity_thunderboard_base.*
+
+//import kotlinx.android.synthetic.main.activity_thunderboard_base.*
abstract class ThunderboardActivity : BaseDemoActivity() {
@@ -25,12 +28,17 @@ abstract class ThunderboardActivity : BaseDemoActivity() {
protected var mainSection: FrameLayout? = null
protected lateinit var statusFragment: StatusFragment
+ private lateinit var binding: ActivityThunderboardBaseBinding
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_thunderboard_base)
- mainSection = main_section as FrameLayout
- statusFragment = supportFragmentManager.findFragmentById(R.id.bluegecko_status_fragment) as StatusFragment
+
+ binding = ActivityThunderboardBaseBinding.inflate(LayoutInflater.from(this))
+ setContentView(binding.root)
+
+ mainSection = binding.mainSection as FrameLayout
+ statusFragment =
+ supportFragmentManager.findFragmentById(R.id.bluegecko_status_fragment) as StatusFragment
}
override fun onBluetoothServiceBound() {
@@ -47,18 +55,51 @@ abstract class ThunderboardActivity : BaseDemoActivity() {
protected fun queueReadingDeviceCharacteristics() {
gattQueue.let {
if (statusFragment.viewModel.thunderboardDevice.value?.name == null) {
- it.queueRead(getDeviceCharacteristic(GattService.GenericAccess, GattCharacteristic.DeviceName))
+ it.queueRead(
+ getDeviceCharacteristic(
+ GattService.GenericAccess,
+ GattCharacteristic.DeviceName
+ )
+ )
}
- it.queueRead(getDeviceCharacteristic(GattService.DeviceInformation, GattCharacteristic.ModelNumberString))
- it.queueRead(getDeviceCharacteristic(GattService.BatteryService, GattCharacteristic.BatteryLevel))
- it.queueRead(getDeviceCharacteristic(GattService.PowerSource, GattCharacteristic.PowerSource))
- it.queueRead(getDeviceCharacteristic(GattService.DeviceInformation, GattCharacteristic.FirmwareRevision))
+ it.queueRead(
+ getDeviceCharacteristic(
+ GattService.DeviceInformation,
+ GattCharacteristic.ModelNumberString
+ )
+ )
+ it.queueRead(
+ getDeviceCharacteristic(
+ GattService.BatteryService,
+ GattCharacteristic.BatteryLevel
+ )
+ )
+ it.queueRead(
+ getDeviceCharacteristic(
+ GattService.PowerSource,
+ GattCharacteristic.PowerSource
+ )
+ )
+ it.queueRead(
+ getDeviceCharacteristic(
+ GattService.DeviceInformation,
+ GattCharacteristic.FirmwareRevision
+ )
+ )
- it.queueNotify(getDeviceCharacteristic(GattService.BatteryService, GattCharacteristic.BatteryLevel))
+ it.queueNotify(
+ getDeviceCharacteristic(
+ GattService.BatteryService,
+ GattCharacteristic.BatteryLevel
+ )
+ )
}
}
- private fun getDeviceCharacteristic(gattService: GattService, characteristic: GattCharacteristic): BluetoothGattCharacteristic? {
+ private fun getDeviceCharacteristic(
+ gattService: GattService,
+ characteristic: GattCharacteristic
+ ): BluetoothGattCharacteristic? {
return gatt?.getService(gattService.number)?.getCharacteristic(characteristic.uuid)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/fragments/StatusFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/fragments/StatusFragment.kt
index 064f4b6c..0e5f46ef 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/fragments/StatusFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/fragments/StatusFragment.kt
@@ -15,16 +15,18 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.siliconlabs.bledemo.bluetooth.ble.GattCharacteristic
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.FragmentDemoBinding
+import com.siliconlabs.bledemo.databinding.FragmentDeviceStatusBinding
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.activities.ThunderboardActivity
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.viewmodels.StatusViewModel
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.models.ThunderBoardDevice
-import kotlinx.android.synthetic.main.fragment_device_status.view.*
+
class StatusFragment : Fragment() {
lateinit var viewModel: StatusViewModel
- private lateinit var rootView: View
+ private lateinit var rootView:FragmentDeviceStatusBinding
private var isConnecting = false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
@@ -34,10 +36,11 @@ class StatusFragment : Fragment() {
setupDataListeners()
- rootView = inflater.inflate(R.layout.fragment_device_status, container, false)
- rootView.battery_indicator.visibility = View.INVISIBLE
- rootView.battery_indicator.setBatteryValue(ThunderBoardDevice.PowerSource.UNKNOWN, 0)
- return rootView
+ rootView = FragmentDeviceStatusBinding.inflate(inflater, container, false)
+
+ rootView.batteryIndicator.visibility = View.INVISIBLE
+ rootView.batteryIndicator.setBatteryValue(ThunderBoardDevice.PowerSource.UNKNOWN, 0)
+ return rootView.root
}
fun handleBaseCharacteristic(characteristic: BluetoothGattCharacteristic) {
@@ -70,12 +73,13 @@ class StatusFragment : Fragment() {
private fun updateStatusViews(device: ThunderBoardDevice) {
rootView.apply {
- device_name.text = device.name
- device_firmware.text =
+
+ deviceName.text = device.name
+ deviceFirmware.text =
if (device.firmwareVersion == null || device.firmwareVersion?.isEmpty()!!) {
getString(R.string.status_no_firmware_version)
} else device.firmwareVersion
- battery_indicator.setBatteryValue(device.powerSource, device.batteryLevel)
+ batteryIndicator.setBatteryValue(device.powerSource, device.batteryLevel)
}
}
@@ -85,20 +89,20 @@ class StatusFragment : Fragment() {
BluetoothProfile.STATE_CONNECTED -> {
resourceId = R.string.status_connected
isConnecting = false
- rootView.battery_indicator.visibility = View.VISIBLE
- rootView.progress_bar.visibility = View.INVISIBLE
+ rootView.batteryIndicator.visibility = View.VISIBLE
+ rootView.progressBar.visibility = View.INVISIBLE
}
BluetoothProfile.STATE_CONNECTING -> {
resourceId = R.string.status_connecting
isConnecting = true
- rootView.battery_indicator.visibility = View.INVISIBLE
- rootView.progress_bar.visibility = View.VISIBLE
+ rootView.batteryIndicator.visibility = View.INVISIBLE
+ rootView.progressBar.visibility = View.VISIBLE
}
BluetoothProfile.STATE_DISCONNECTING -> {
resourceId = BluetoothProfile.STATE_DISCONNECTING
isConnecting = false
- rootView.battery_indicator.visibility = View.INVISIBLE
- rootView.progress_bar.visibility = View.VISIBLE
+ rootView.batteryIndicator.visibility = View.INVISIBLE
+ rootView.progressBar.visibility = View.VISIBLE
}
else -> {
val titleId: Int
@@ -112,13 +116,13 @@ class StatusFragment : Fragment() {
}
resourceId = R.string.status_disconnected
isConnecting = false
- rootView.battery_indicator.visibility = View.INVISIBLE
- rootView.progress_bar.visibility = View.VISIBLE
+ rootView.batteryIndicator.visibility = View.INVISIBLE
+ rootView.progressBar.visibility = View.VISIBLE
animateDown()
showNotConnectedDialog(viewModel.thunderboardDevice.value?.name, titleId, messageId)
}
}
- rootView.device_status.text = getString(resourceId)
+ rootView.deviceStatus.text = getString(resourceId)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/ui/BatteryIndicator.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/ui/BatteryIndicator.kt
index db6f5fc3..8c88cdbd 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/ui/BatteryIndicator.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/ui/BatteryIndicator.kt
@@ -5,35 +5,42 @@ import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.BatteryIndicatorBinding
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.models.ThunderBoardDevice
-import kotlinx.android.synthetic.main.battery_indicator.view.*
-class BatteryIndicator @JvmOverloads constructor(context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
+//import kotlinx.android.synthetic.main.battery_indicator.view.*
+
+class BatteryIndicator @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
+ private lateinit var binding: BatteryIndicatorBinding
fun setBatteryValue(powerSource: ThunderBoardDevice.PowerSource, batteryValue: Int) {
when (powerSource) {
ThunderBoardDevice.PowerSource.UNKNOWN -> {
- battery_percent.setText(R.string.unknown_power)
- battery_meter.setImageResource(R.drawable.icn_signal_unknown)
+
+ binding.batteryPercent.setText(R.string.unknown_power)
+ binding.batteryMeter.setImageResource(R.drawable.icn_signal_unknown)
}
+
ThunderBoardDevice.PowerSource.USB -> {
- battery_percent.setText(R.string.usb_power)
- battery_meter.setImageResource(R.drawable.icon_usb)
+ binding.batteryPercent.setText(R.string.usb_power)
+ binding.batteryMeter.setImageResource(R.drawable.icon_usb)
}
+
else -> {
- battery_percent.text = String.format("%d%%", batteryValue)
- battery_meter.setValue(batteryValue)
+ binding.batteryPercent.text = String.format("%d%%", batteryValue)
+ binding.batteryMeter.setValue(batteryValue)
}
}
}
init {
val inflater = LayoutInflater.from(context)
- val view = inflater.inflate(R.layout.battery_indicator, this, false)
- addView(view)
+ binding = BatteryIndicatorBinding.inflate(inflater, this, false)
+ addView(binding.root)
}
}
\ No newline at end of file
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 fbc1114b..c12dc1f2 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
@@ -1,5 +1,6 @@
package com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.blinky_thunderboard.activities
+//import kotlinx.android.synthetic.main.activity_blinky_thunderboard.*
import android.annotation.SuppressLint
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
@@ -10,18 +11,17 @@ import android.view.View
import androidx.cardview.widget.CardView
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
-import com.siliconlabs.bledemo.home_screen.dialogs.SelectDeviceDialog
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.blinky_thunderboard.viewmodels.BlinkyThunderboardViewModel
+import com.siliconlabs.bledemo.databinding.ActivityBlinkyThunderboardBinding
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.activities.ThunderboardActivity
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.models.ThunderBoardDevice
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.blinky_thunderboard.control.ColorLEDControl
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.blinky_thunderboard.control.ColorLEDControl.ColorLEDControlListener
-import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.activities.ThunderboardActivity
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.blinky_thunderboard.model.LedRGBState
-import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.models.ThunderBoardDevice
-import kotlinx.android.synthetic.main.activity_blinky_thunderboard.*
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.blinky_thunderboard.viewmodels.BlinkyThunderboardViewModel
+import com.siliconlabs.bledemo.home_screen.dialogs.SelectDeviceDialog
import java.util.*
class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListener {
@@ -30,18 +30,20 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
private lateinit var colorLEDControl: ColorLEDControl
private lateinit var viewModel: BlinkyThunderboardViewModel
+ private lateinit var binding:ActivityBlinkyThunderboardBinding
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
- ledsControl = view.findViewById(R.id.leds_control)
+ binding = ActivityBlinkyThunderboardBinding. inflate(LayoutInflater.from(this), null, false)
+
+ colorLEDControl = binding.colorLedControl // make the view gone (if necessary) before it can be showed
+ ledsControl = binding.ledsControl
val powerSourceIntent = intent.getIntExtra(SelectDeviceDialog.POWER_SOURCE_EXTRA, 0)
val modelNumberIntent = intent.getStringExtra(SelectDeviceDialog.MODEL_TYPE_EXTRA)
setControlsVisibility(ThunderBoardDevice.PowerSource.fromInt(powerSourceIntent), modelNumberIntent)
- mainSection?.addView(view)
+ mainSection?.addView(binding.root)
viewModel = ViewModelProvider(this).get(BlinkyThunderboardViewModel::class.java)
@@ -50,20 +52,21 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
}
private fun setupUiListeners() {
- led_0.setOnCheckedChangeListener { _, isChecked ->
+
+ binding.led0.setOnCheckedChangeListener { _, isChecked ->
var action = 0
if (isChecked) action = BlinkyThunderboardViewModel.LED_0_ON
- if (led_1.isChecked) action = action or BlinkyThunderboardViewModel.LED_1_ON
+ if (binding.led1.isChecked) action = action or BlinkyThunderboardViewModel.LED_1_ON
getDigitalWriteCharacteristic()?.apply {
value = byteArrayOf(action.toByte())
gattQueue.queueWrite(this)
}
}
- led_1.setOnCheckedChangeListener { _, isChecked ->
+ binding.led1.setOnCheckedChangeListener { _, isChecked ->
var action = 0
if (isChecked) action = BlinkyThunderboardViewModel.LED_1_ON
- if (led_0.isChecked) action = action or BlinkyThunderboardViewModel.LED_0_ON
+ if (binding.led0.isChecked) action = action or BlinkyThunderboardViewModel.LED_0_ON
getDigitalWriteCharacteristic()?.apply {
value = byteArrayOf(action.toByte())
@@ -74,12 +77,13 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
}
private fun setupDataListeners(modelNumber: String?) {
- viewModel.button0.observe(this, Observer { switch_0.setChecked(it) })
- viewModel.button1.observe(this, Observer { switch_1.setChecked(it) })
+
+ viewModel.button0.observe(this, Observer { binding.switch0.setChecked(it) })
+ viewModel.button1.observe(this, Observer { binding.switch1.setChecked(it) })
viewModel.led0.observe(this, Observer {
- if (it != led_0.isChecked) led_0.isChecked = it })
+ if (it != binding.led0.isChecked) binding.led0.isChecked = it })
viewModel.led1.observe(this, Observer {
- if (it != led_1.isChecked) led_1.isChecked = it })
+ if (it != binding.led1.isChecked) binding.led1.isChecked = it })
when (modelNumber) {
ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3,
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/control/ColorLEDControl.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/control/ColorLEDControl.kt
index 73241ea1..53a547d0 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/control/ColorLEDControl.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/control/ColorLEDControl.kt
@@ -12,15 +12,17 @@ import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import androidx.appcompat.widget.SwitchCompat
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.IodemoColorLedsBinding
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.blinky_thunderboard.model.LedRGBState
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.blinky_thunderboard.ui.ColorLEDs
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.blinky_thunderboard.ui.HueBackgroundView
-import kotlinx.android.synthetic.main.iodemo_color_leds.view.*
+
+//import kotlinx.android.synthetic.main.iodemo_color_leds.view.*
class ColorLEDControl @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private lateinit var colorLEDs: ColorLEDs
@@ -31,29 +33,32 @@ class ColorLEDControl @JvmOverloads constructor(
private var hue: Float = 0f // from 0 to 360
private var brightness: Float = 1f // from 0 to 1
+ private lateinit var binding: IodemoColorLedsBinding //iodemo_color_leds
private var colorLEDControlListener: ColorLEDControlListener? = null
- private fun setupViews(rootView: LinearLayout) {
- colorLEDs = rootView.iodemo_color_leds
- hueSelect = rootView.iodemo_hue_select
- brightnessSelect = rootView.iodemo_brightness_select
- colorSwitch = rootView.iodemo_color_switch
- hueBackgroundView = rootView.iodemo_hue_background
+ private fun setupViews(rootView: IodemoColorLedsBinding) {
+
+ colorLEDs = rootView.iodemoColorLeds
+ hueSelect = rootView.iodemoHueSelect
+ brightnessSelect = rootView.iodemoBrightnessSelect
+ colorSwitch = rootView.iodemoColorSwitch
+ hueBackgroundView = rootView.iodemoHueBackground
}
- private var selectBrightnessListener: OnSeekBarChangeListener = object : OnSeekBarChangeListener {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- brightness = findBrightness(progress)
- setColorLEDs(colorSwitch.isChecked, hue, brightness)
- colorLEDs.setAlpha(progress)
- }
+ private var selectBrightnessListener: OnSeekBarChangeListener =
+ object : OnSeekBarChangeListener {
+ override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+ brightness = findBrightness(progress)
+ setColorLEDs(colorSwitch.isChecked, hue, brightness)
+ colorLEDs.setAlpha(progress)
+ }
- override fun onStartTrackingTouch(seekBar: SeekBar) {}
- override fun onStopTrackingTouch(seekBar: SeekBar) {
- colorLEDControlListener?.onLedUpdateStop()
+ override fun onStartTrackingTouch(seekBar: SeekBar) {}
+ override fun onStopTrackingTouch(seekBar: SeekBar) {
+ colorLEDControlListener?.onLedUpdateStop()
+ }
}
- }
fun setColorLEDControlListener(listener: ColorLEDControlListener?) {
colorLEDControlListener = listener
@@ -65,10 +70,11 @@ class ColorLEDControl @JvmOverloads constructor(
enableControls(isOn)
val hsv = FloatArray(3)
Color.RGBToHSV(
- colorLEDsValue.red,
- colorLEDsValue.green,
- colorLEDsValue.blue,
- hsv)
+ colorLEDsValue.red,
+ colorLEDsValue.green,
+ colorLEDsValue.blue,
+ hsv
+ )
hue = hsv[0]
brightness = hsv[2]
hueSelect.progress = hue.toInt()
@@ -97,12 +103,14 @@ class ColorLEDControl @JvmOverloads constructor(
private fun setColorLEDs(switchState: Boolean, hue: Float, brightness: Float) {
val color = hsvToRGB(hue, brightness)
- colorLEDControlListener?.updateColorLEDs(LedRGBState(
+ colorLEDControlListener?.updateColorLEDs(
+ LedRGBState(
switchState,
Color.red(color),
Color.green(color),
Color.blue(color)
- ))
+ )
+ )
}
private fun hsvToRGB(hue: Float, brightness: Float): Int {
@@ -127,10 +135,11 @@ class ColorLEDControl @JvmOverloads constructor(
}
init {
- val layout = LayoutInflater.from(context).inflate(
- R.layout.iodemo_color_leds, this, false) as LinearLayout
+// val layout = LayoutInflater.from(context).inflate(
+// R.layout.iodemo_color_leds, this, false) as LinearLayout
+ val layout = IodemoColorLedsBinding.inflate(LayoutInflater.from(context))
setupViews(layout)
- addView(layout)
+ addView(layout.root)
val color = hsvToRGB(hue, brightness)
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/control/SwitchControl.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/control/SwitchControl.kt
index 9a38c675..943f463f 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/control/SwitchControl.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/control/SwitchControl.kt
@@ -5,26 +5,30 @@ import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.switch_control.view.*
+import com.siliconlabs.bledemo.databinding.SwitchControlBinding
+
+//import kotlinx.android.synthetic.main.switch_control.view.*
class SwitchControl @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
+ private lateinit var binding: SwitchControlBinding
fun setChecked(checked: Boolean) {
- switch_image.setImageResource(
- if (checked) R.drawable.switch_status_on
- else R.drawable.switch_status_off
+ binding.switchImage.setImageResource(
+ if (checked) R.drawable.switch_status_on
+ else R.drawable.switch_status_off
)
- switch_text.text = context.getString(if (checked) R.string.blinky_tb_on else R.string.blinky_tb_off)
+ binding.switchText.text =
+ context.getString(if (checked) R.string.blinky_tb_on else R.string.blinky_tb_off)
}
init {
val inflater = LayoutInflater.from(context)
- val view = inflater.inflate(R.layout.switch_control, null, false)
- addView(view)
+ binding = SwitchControlBinding.inflate(inflater, null, false)
+ addView(binding.root)
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/activities/EnvironmentActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/activities/EnvironmentActivity.kt
index 83a4abc7..2a03ee5f 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/activities/EnvironmentActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/activities/EnvironmentActivity.kt
@@ -16,25 +16,24 @@ import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
+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.environment.viewmodels.EnvironmentViewModel
-import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.dialogs.SettingsDialog
-import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.control.*
-import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.HallState
-import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.TemperatureScale
-import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.utils.SensorChecker.ThunderboardSensor
+import com.siliconlabs.bledemo.databinding.ActivityEnvironmentBinding
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.activities.ThunderboardActivity
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.models.ThunderBoardDevice
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.utils.SensorChecker
-import com.siliconlabs.bledemo.features.scan.browser.activities.DeviceServicesActivity
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.utils.SensorChecker.ThunderboardSensor
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.control.*
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.dialogs.SettingsDialog
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.HallState
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.TemperatureScale
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.viewmodels.EnvironmentViewModel
import com.siliconlabs.bledemo.utils.BLEUtils
import com.siliconlabs.bledemo.utils.Converters
-import kotlinx.android.synthetic.main.activity_environment.*
import timber.log.Timber
class EnvironmentActivity : ThunderboardActivity() {
@@ -43,14 +42,18 @@ class EnvironmentActivity : ThunderboardActivity() {
private var hallStateControl: HallStateControl? = null
private lateinit var viewModel: EnvironmentViewModel
+ private lateinit var binding: ActivityEnvironmentBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val view = LayoutInflater
- .from(this).inflate(R.layout.activity_environment, null, false)
- mainSection?.addView(view)
- viewModel = ViewModelProvider(this,
- EnvironmentViewModel.Factory(this)).get(EnvironmentViewModel::class.java)
+ binding = ActivityEnvironmentBinding.inflate(
+ layoutInflater
+ )
+ mainSection?.addView(binding.root)
+ viewModel = ViewModelProvider(
+ this,
+ EnvironmentViewModel.Factory(this)
+ ).get(EnvironmentViewModel::class.java)
setupDataListeners()
}
@@ -104,7 +107,8 @@ class EnvironmentActivity : ThunderboardActivity() {
controls[ThunderboardSensor.MagneticField]?.setHallStrength(it)
})
viewModel.hallState.observe(this, Observer {
- hallStateControl?.setHallState(it)
+ // hallStateControl?.setHallState(it)
+ controls[ThunderboardSensor.DoorState]?.setHallState(it)
})
}
@@ -113,10 +117,14 @@ class EnvironmentActivity : ThunderboardActivity() {
it.value == SensorChecker.SensorState.WORKING
}.any()
val dialogMessage =
- if (isAnySensorWorking) getString(R.string.sensor_malfunction_dialog_message,
- TextUtils.join(", ", brokenSensors))
- else getString(R.string.critical_sensor_malfunction_dialog_message,
- TextUtils.join(", ", brokenSensors))
+ if (isAnySensorWorking) getString(
+ R.string.sensor_malfunction_dialog_message,
+ TextUtils.join(", ", brokenSensors)
+ )
+ else getString(
+ R.string.critical_sensor_malfunction_dialog_message,
+ TextUtils.join(", ", brokenSensors)
+ )
AlertDialog.Builder(this).apply {
setTitle(getString(R.string.sensor_malfunction_dialog_title))
@@ -154,10 +162,12 @@ class EnvironmentActivity : ThunderboardActivity() {
gatt?.disconnect()
true
}
+
R.id.action_settings -> {
showSettings()
true
}
+
else -> super.onOptionsItemSelected(item)
}
}
@@ -187,7 +197,7 @@ class EnvironmentActivity : ThunderboardActivity() {
}
private fun initGrid() {
- env_grid.apply {
+ binding.envGrid.apply {
sensorChecker.environmentSensors.filter {
it.value == SensorChecker.SensorState.WORKING
}.forEach {
@@ -195,45 +205,70 @@ class EnvironmentActivity : ThunderboardActivity() {
if (it.key == ThunderboardSensor.TVOC && !isPowerSufficient()) return@forEach
if (it.key != ThunderboardSensor.DoorState) {
- controls[it.key] = EnvironmentControl(this@EnvironmentActivity,
- getString(getTileDescription(it.key)),
- ContextCompat.getDrawable(this@EnvironmentActivity, getTileIcon(it.key))).also {
- runOnUiThread { addView(it) }
+ controls[it.key] = EnvironmentControl(
+ this@EnvironmentActivity,
+ getString(getTileDescription(it.key)),
+ ContextCompat.getDrawable(this@EnvironmentActivity, getTileIcon(it.key))
+ ).also {
+ runOnUiThread { addView(it.tileView.root) }
}
} else {
- hallStateControl = HallStateControl(this@EnvironmentActivity,
- getString(getTileDescription(it.key)),
- ContextCompat.getDrawable(this@EnvironmentActivity, getTileIcon(it.key))).also {
- it.setOnClickListener { onHallStateClick() }
- runOnUiThread { addView(it) }
+
+ controls[it.key] = EnvironmentControl(
+ this@EnvironmentActivity,
+ getString(getTileDescription(it.key)),
+ ContextCompat.getDrawable(this@EnvironmentActivity, getTileIcon(it.key))
+ ).also {
+ runOnUiThread { addView(it.tileView.root) }
}
}
}
}
+
}
private fun setupSensorCharacteristics() {
sensorChecker.let {
- it.setupEnvSensorCharacteristic(ThunderboardSensor.Temperature,
- getEnvironmentalSensingCharacteristic(GattCharacteristic.EnvironmentTemperature))
- it.setupEnvSensorCharacteristic(ThunderboardSensor.Humidity,
- getEnvironmentalSensingCharacteristic(GattCharacteristic.Humidity))
- it.setupEnvSensorCharacteristic(ThunderboardSensor.UvIndex,
- getEnvironmentalSensingCharacteristic(GattCharacteristic.UvIndex))
- it.setupEnvSensorCharacteristic(ThunderboardSensor.Pressure,
- getEnvironmentalSensingCharacteristic(GattCharacteristic.Pressure))
- it.setupEnvSensorCharacteristic(ThunderboardSensor.SoundLevel,
- getEnvironmentalSensingCharacteristic(GattCharacteristic.SoundLevel))
- it.setupEnvSensorCharacteristic(ThunderboardSensor.AmbientLight,
- getAmbientLightCharacteristic())
- it.setupEnvSensorCharacteristic(ThunderboardSensor.CO2,
- getAirQualityCharacteristic(GattCharacteristic.CO2Reading))
- it.setupEnvSensorCharacteristic(ThunderboardSensor.TVOC,
- getAirQualityCharacteristic(GattCharacteristic.TVOCReading))
- it.setupEnvSensorCharacteristic(ThunderboardSensor.MagneticField,
- getHallEffectCharacteristic(GattCharacteristic.HallFieldStrength))
- it.setupEnvSensorCharacteristic(ThunderboardSensor.DoorState,
- getHallEffectCharacteristic(GattCharacteristic.HallState))
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.Temperature,
+ getEnvironmentalSensingCharacteristic(GattCharacteristic.EnvironmentTemperature)
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.Humidity,
+ getEnvironmentalSensingCharacteristic(GattCharacteristic.Humidity)
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.UvIndex,
+ getEnvironmentalSensingCharacteristic(GattCharacteristic.UvIndex)
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.Pressure,
+ getEnvironmentalSensingCharacteristic(GattCharacteristic.Pressure)
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.SoundLevel,
+ getEnvironmentalSensingCharacteristic(GattCharacteristic.SoundLevel)
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.AmbientLight,
+ getAmbientLightCharacteristic()
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.CO2,
+ getAirQualityCharacteristic(GattCharacteristic.CO2Reading)
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.TVOC,
+ getAirQualityCharacteristic(GattCharacteristic.TVOCReading)
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.MagneticField,
+ getHallEffectCharacteristic(GattCharacteristic.HallFieldStrength)
+ )
+ it.setupEnvSensorCharacteristic(
+ ThunderboardSensor.DoorState,
+ getHallEffectCharacteristic(GattCharacteristic.HallState)
+ )
}
}
@@ -253,26 +288,28 @@ class EnvironmentActivity : ThunderboardActivity() {
}
private fun getEnvironmentalSensingCharacteristic(characteristic: GattCharacteristic): BluetoothGattCharacteristic? {
- return gatt?.getService(GattService.EnvironmentalSensing.number)?.
- getCharacteristic(characteristic.uuid)
+ return gatt?.getService(GattService.EnvironmentalSensing.number)
+ ?.getCharacteristic(characteristic.uuid)
}
private fun getAirQualityCharacteristic(characteristic: GattCharacteristic): BluetoothGattCharacteristic? {
- return gatt?.getService(GattService.IndoorAirQuality.number)?.
- getCharacteristic(characteristic.uuid)
+ return gatt?.getService(GattService.IndoorAirQuality.number)
+ ?.getCharacteristic(characteristic.uuid)
}
private fun getHallEffectCharacteristic(characteristic: GattCharacteristic): BluetoothGattCharacteristic? {
- return gatt?.getService(GattService.HallEffect.number)?.
- getCharacteristic(characteristic.uuid)
+ return gatt?.getService(GattService.HallEffect.number)
+ ?.getCharacteristic(characteristic.uuid)
}
- private fun getAmbientLightCharacteristic() : BluetoothGattCharacteristic? {
+ private fun getAmbientLightCharacteristic(): BluetoothGattCharacteristic? {
val lightReact = getEnvironmentalSensingCharacteristic(GattCharacteristic.AmbientLightReact)
if (lightReact != null) return lightReact
- val lightReact2 = BLEUtils.getCharacteristic(gatt, GattService.AmbientLight,
- GattCharacteristic.AmbientLightReact)
+ val lightReact2 = BLEUtils.getCharacteristic(
+ gatt, GattService.AmbientLight,
+ GattCharacteristic.AmbientLightReact
+ )
if (lightReact2 != null) return lightReact2
val lightSense = getEnvironmentalSensingCharacteristic(GattCharacteristic.AmbientLightSense)
@@ -282,7 +319,7 @@ class EnvironmentActivity : ThunderboardActivity() {
}
@StringRes
- private fun getTileDescription(sensor: ThunderboardSensor) : Int {
+ private fun getTileDescription(sensor: ThunderboardSensor): Int {
return when (sensor) {
ThunderboardSensor.Temperature -> R.string.environment_temp
ThunderboardSensor.Humidity -> R.string.environment_humidity
@@ -299,7 +336,7 @@ class EnvironmentActivity : ThunderboardActivity() {
}
@DrawableRes
- private fun getTileIcon(sensor: ThunderboardSensor) : Int {
+ private fun getTileIcon(sensor: ThunderboardSensor): Int {
return when (sensor) {
ThunderboardSensor.Temperature -> R.drawable.icon_temp
ThunderboardSensor.Humidity -> R.drawable.icon_environment
@@ -333,9 +370,11 @@ class EnvironmentActivity : ThunderboardActivity() {
queueReadingEnvironmentalData()
}
- 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
@@ -347,36 +386,54 @@ class EnvironmentActivity : ThunderboardActivity() {
GattCharacteristic.ModelNumberString,
GattCharacteristic.BatteryLevel,
GattCharacteristic.PowerSource,
- GattCharacteristic.FirmwareRevision -> statusFragment.handleBaseCharacteristic(characteristic)
+ GattCharacteristic.FirmwareRevision -> statusFragment.handleBaseCharacteristic(
+ characteristic
+ )
GattCharacteristic.EnvironmentTemperature -> {
val temperature = characteristic.getIntValue(gattCharacteristic.format, 0)
if (setup) {
- sensorChecker.checkIfEnvSensorBroken(ThunderboardSensor.Temperature, temperature.toLong())
+ sensorChecker.checkIfEnvSensorBroken(
+ ThunderboardSensor.Temperature,
+ temperature.toLong()
+ )
} else viewModel.incrementControlsRead()
viewModel.temperature.postValue(temperature / 100.0f)
}
+
GattCharacteristic.Humidity -> {
val humidity = characteristic.getIntValue(gattCharacteristic.format, 0)
if (setup) {
- sensorChecker.checkIfEnvSensorBroken(ThunderboardSensor.Humidity, humidity.toLong())
+ sensorChecker.checkIfEnvSensorBroken(
+ ThunderboardSensor.Humidity,
+ humidity.toLong()
+ )
} else viewModel.incrementControlsRead()
viewModel.humidity.postValue(humidity / 100)
}
+
GattCharacteristic.UvIndex -> {
val uvIndex = characteristic.getIntValue(gattCharacteristic.format, 0)
if (setup) {
- sensorChecker.checkIfEnvSensorBroken(ThunderboardSensor.UvIndex, uvIndex.toLong())
+ sensorChecker.checkIfEnvSensorBroken(
+ ThunderboardSensor.UvIndex,
+ uvIndex.toLong()
+ )
} else viewModel.incrementControlsRead()
viewModel.uvIndex.postValue(uvIndex)
}
+
GattCharacteristic.SoundLevel -> {
val soundLevel = characteristic.getIntValue(gattCharacteristic.format, 0)
if (setup) {
- sensorChecker.checkIfEnvSensorBroken(ThunderboardSensor.SoundLevel, soundLevel.toLong())
+ sensorChecker.checkIfEnvSensorBroken(
+ ThunderboardSensor.SoundLevel,
+ soundLevel.toLong()
+ )
} else viewModel.incrementControlsRead()
viewModel.soundLevel.postValue(soundLevel / 100)
}
+
GattCharacteristic.Pressure -> {
val pressure = Converters.calculateLongValue(characteristic.value, false)
if (setup) {
@@ -384,24 +441,36 @@ class EnvironmentActivity : ThunderboardActivity() {
} else viewModel.incrementControlsRead()
viewModel.pressure.postValue(pressure / 1000)
}
+
GattCharacteristic.CO2Reading -> {
val co2Level = characteristic.getIntValue(gattCharacteristic.format, 0)
if (setup) {
- sensorChecker.checkIfEnvSensorBroken(ThunderboardSensor.CO2, co2Level.toLong())
+ sensorChecker.checkIfEnvSensorBroken(
+ ThunderboardSensor.CO2,
+ co2Level.toLong()
+ )
} else viewModel.incrementControlsRead()
viewModel.co2Level.postValue(co2Level)
}
+
GattCharacteristic.TVOCReading -> {
val tvocLevel = characteristic.getIntValue(gattCharacteristic.format, 0)
if (setup) {
- sensorChecker.checkIfEnvSensorBroken(ThunderboardSensor.TVOC, tvocLevel.toLong())
+ sensorChecker.checkIfEnvSensorBroken(
+ ThunderboardSensor.TVOC,
+ tvocLevel.toLong()
+ )
} else viewModel.incrementControlsRead()
viewModel.tvocLevel.postValue(tvocLevel)
}
+
GattCharacteristic.HallFieldStrength -> {
val hallStrength = characteristic.getIntValue(gattCharacteristic.format, 0)
if (setup) {
- sensorChecker.checkIfEnvSensorBroken(ThunderboardSensor.MagneticField, hallStrength.toLong())
+ sensorChecker.checkIfEnvSensorBroken(
+ ThunderboardSensor.MagneticField,
+ hallStrength.toLong()
+ )
val brokenSensors = sensorChecker.environmentSensors.filter {
it.value == SensorChecker.SensorState.BROKEN
}.keys
@@ -417,6 +486,7 @@ class EnvironmentActivity : ThunderboardActivity() {
viewModel.hallStrength.postValue(hallStrength)
}
+
GattCharacteristic.HallState -> {
val hallState = characteristic.getIntValue(gattCharacteristic.format, 0)
viewModel.hallState.postValue(HallState.fromValue(hallState))
@@ -433,21 +503,27 @@ class EnvironmentActivity : ThunderboardActivity() {
GattCharacteristic.AmbientLightSense -> {
var ambientLight = Converters.calculateLongValue(characteristic.value, false)
if (setup) {
- sensorChecker.checkIfEnvSensorBroken(ThunderboardSensor.AmbientLight, ambientLight)
+ sensorChecker.checkIfEnvSensorBroken(
+ ThunderboardSensor.AmbientLight,
+ ambientLight
+ )
} else viewModel.incrementControlsRead()
ambientLight /= 100
viewModel.ambientLight.postValue(
- if (ambientLight > MAX_AMBIENT_LIGHT) MAX_AMBIENT_LIGHT.toLong()
- else ambientLight
+ if (ambientLight > MAX_AMBIENT_LIGHT) MAX_AMBIENT_LIGHT.toLong()
+ else ambientLight
)
}
- 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
@@ -457,25 +533,34 @@ class EnvironmentActivity : ThunderboardActivity() {
}
}
- 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.HallState -> {
val hallState = characteristic.getIntValue(gattCharacteristic.format, 0)
viewModel.hallState.postValue(HallState.fromValue(hallState))
}
- else -> { }
+
+ else -> {}
}
}
- 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()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/control/EnvironmentControl.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/control/EnvironmentControl.kt
index c29524e2..caa0e1ae 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/control/EnvironmentControl.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/control/EnvironmentControl.kt
@@ -2,74 +2,123 @@ package com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environme
import android.content.Context
import android.graphics.drawable.Drawable
+import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.annotation.StringRes
+import androidx.annotation.StyleRes
import androidx.gridlayout.widget.GridLayout
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.EnvironmentdemoTileBinding
+import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.HallState
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.TemperatureScale
-import kotlinx.android.synthetic.main.environmentdemo_tile.view.*
+
+//import kotlinx.android.synthetic.main.environmentdemo_tile.view.*
open class EnvironmentControl(
- context: Context,
- description: String?,
- icon: Drawable?
+ context: Context,
+ description: String?,
+ icon: Drawable?
) : LinearLayout(context, null, 0) {
- constructor(context: Context) : this(context, null, null)
- private val tileView: View = inflate(context, R.layout.environmentdemo_tile, this)
+ constructor(context: Context) : this(context, null, null)
+ val tileView = EnvironmentdemoTileBinding.inflate(LayoutInflater.from(context))
+ lateinit var resetTamperTextView: TextView
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)
+
+ tileView.envValue.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)
+ tileView.envValue.text =
+ String.format(context.getString(R.string.environment_humidity_measure), humidity)
}
fun setUVIndex(uvIndex: Int) {
- tileView.env_value.text = String.format(context.getString(R.string.environment_uv_unit), uvIndex)
+ tileView.envValue.text =
+ String.format(context.getString(R.string.environment_uv_unit), uvIndex)
}
fun setAmbientLight(ambientLight: Long) {
- tileView.env_value.text = String.format(context.getString(R.string.environment_ambient_lx), ambientLight)
+ tileView.envValue.text =
+ String.format(context.getString(R.string.environment_ambient_lx), ambientLight)
}
fun setSoundLevel(soundLevel: Int) {
- tileView.env_value.text = String.format(context.getString(R.string.environment_sound_level_measure), soundLevel)
+ tileView.envValue.text =
+ String.format(context.getString(R.string.environment_sound_level_measure), soundLevel)
}
fun setPressure(pressure: Long) {
- tileView.env_value.text = String.format(context.getString(R.string.environment_pressure_measure), pressure)
+ tileView.envValue.text =
+ String.format(context.getString(R.string.environment_pressure_measure), pressure)
}
fun setCO2(co2Level: Int) {
- tileView.env_value.text = String.format(context.getString(R.string.environment_co2_measure), co2Level)
+ tileView.envValue.text =
+ String.format(context.getString(R.string.environment_co2_measure), co2Level)
}
fun setVOC(vocLevel: Int) {
- tileView.env_value.text = String.format(context.getString(R.string.environment_voc_measure), vocLevel)
+ tileView.envValue.text =
+ String.format(context.getString(R.string.environment_voc_measure), vocLevel)
}
fun setHallStrength(hallStrength: Int) {
- tileView.env_value.text = context.getString(R.string.environment_hall_strength_measure, hallStrength)
+ tileView.envValue.text =
+ context.getString(R.string.environment_hall_strength_measure, hallStrength)
}
init {
+ if(description!!.contains(context.getString(R.string.environment_hall_state))){
+ resetTamperTextView = TextView(context).apply {
+ setText(R.string.environment_hall_state_reset_tamper)
+ setTextAppearance(R.style.EnvironmentControlLabel_HallStateTampered)
+ visibility = GONE
+ }
+ tileView.envLayout.addView(resetTamperTextView)
+ tileView.cardviewEnvTile.isEnabled = false
+ }
tileView.apply {
- env_description.text = description
- env_value.text = context.getString(R.string.environment_not_initialized)
- env_icon.setImageDrawable(icon)
+ envDescription.text = description
+ envValue.text = context.getString(R.string.environment_not_initialized)
+ envIcon.setImageDrawable(icon)
}
layoutParams = GridLayout.LayoutParams(
- GridLayout.spec(GridLayout.UNDEFINED, 1f),
- GridLayout.spec(GridLayout.UNDEFINED, 1f)).apply {
+ GridLayout.spec(GridLayout.UNDEFINED, 1f),
+ GridLayout.spec(GridLayout.UNDEFINED, 1f)
+ ).apply {
width = 0
}
}
+ fun setHallState(hallState: HallState) {
+ var resetTamperVisible = GONE
+ @StringRes var hallStateTextResId = R.string.environment_not_initialized
+ @StyleRes var hallStateStyleResId = R.style.tb_robo_medium_18dp
+
+ when (hallState) {
+ HallState.TAMPERED -> {
+ resetTamperVisible = VISIBLE
+ hallStateTextResId = R.string.environment_hall_state_tampered
+ hallStateStyleResId = R.style.EnvironmentControlLabel_HallStateTampered
+ }
+
+ HallState.CLOSED -> hallStateTextResId = R.string.environment_hall_state_closed
+ HallState.OPENED -> hallStateTextResId = R.string.environment_hall_state_opened
+ }
+
+ tileView.envValue.text = context.getString(hallStateTextResId)
+ tileView.envValue.setTextAppearance(hallStateStyleResId)
+ resetTamperTextView.visibility = resetTamperVisible
+ }
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/control/HallStateControl.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/control/HallStateControl.kt
index 5cfe6ebc..d3700bbd 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/control/HallStateControl.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/control/HallStateControl.kt
@@ -2,13 +2,15 @@ package com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environme
import android.content.Context
import android.graphics.drawable.Drawable
-import android.view.View
+import android.view.LayoutInflater
import android.widget.TextView
import androidx.annotation.StringRes
import androidx.annotation.StyleRes
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.EnvironmentdemoTileBinding
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.HallState
-import kotlinx.android.synthetic.main.environmentdemo_tile.view.*
+
+//import kotlinx.android.synthetic.main.environmentdemo_tile.view.*
/**
* Displays an icon and the Hall State value in a combo control.
@@ -17,14 +19,14 @@ import kotlinx.android.synthetic.main.environmentdemo_tile.view.*
* The HallStateMeter and the TextView are added to the layout dynamically
*/
class HallStateControl(
- context: Context,
- description: String?,
- icon: Drawable?
+ context: Context,
+ description: String?,
+ icon: Drawable?
) : EnvironmentControl(context, description, icon) {
constructor(context: Context) : this(context, null, null)
- private val tileView: View = inflate(context, R.layout.environmentdemo_tile, this)
+ /*val tileViewHallState = EnvironmentdemoTileBinding.inflate(LayoutInflater.from(context))
private val resetTamperTextView: TextView
fun setHallState(hallState: HallState) {
@@ -38,12 +40,13 @@ class HallStateControl(
hallStateTextResId = R.string.environment_hall_state_tampered
hallStateStyleResId = R.style.EnvironmentControlLabel_HallStateTampered
}
+
HallState.CLOSED -> hallStateTextResId = R.string.environment_hall_state_closed
HallState.OPENED -> hallStateTextResId = R.string.environment_hall_state_opened
}
- tileView.env_value.text = context.getString(hallStateTextResId)
- tileView.env_value.setTextAppearance(hallStateStyleResId)
+ tileViewHallState.envValue.text = context.getString(hallStateTextResId)
+ tileViewHallState.envValue.setTextAppearance(hallStateStyleResId)
resetTamperTextView.visibility = resetTamperVisible
}
@@ -53,7 +56,7 @@ class HallStateControl(
setTextAppearance(R.style.EnvironmentControlLabel_HallStateTampered)
visibility = GONE
}
- env_layout.addView(resetTamperTextView)
- cardview_env_tile.isEnabled = false
- }
+ tileViewHallState.envLayout.addView(resetTamperTextView)
+ tileViewHallState.cardviewEnvTile.isEnabled = false
+ }*/
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/dialogs/SettingsDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/dialogs/SettingsDialog.kt
index 37519c75..5e418d6e 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/dialogs/SettingsDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/environment/dialogs/SettingsDialog.kt
@@ -11,22 +11,24 @@ import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.databinding.DialogSettingsBinding
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.TemperatureScale
import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.utils.PreferenceManager
-import kotlinx.android.synthetic.main.dialog_settings.*
+
class SettingsDialog(
- context: Context,
- private val settingsHandler: SettingsHandler
+ context: Context,
+ private val settingsHandler: SettingsHandler
) : BaseDialogFragment(
- hasCustomWidth = true,
- isCanceledOnTouchOutside = true
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = true
) {
private val prefsManager = PreferenceManager(context)
private lateinit var _binding: DialogSettingsBinding
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View {
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
_binding = DialogSettingsBinding.inflate(inflater)
return _binding.root
}
@@ -49,9 +51,9 @@ class SettingsDialog(
private fun loadPersonalize() {
prefsManager.preferences.let {
if (it.scale == TemperatureScale.CELSIUS) {
- temperature_toggle.check(R.id.celsius)
+ _binding.temperatureToggle.check(R.id.celsius)
} else if (it.scale == TemperatureScale.FAHRENHEIT) {
- temperature_toggle.check(R.id.fahrenheit)
+ _binding.temperatureToggle.check(R.id.fahrenheit)
}
}
}
@@ -59,8 +61,8 @@ class SettingsDialog(
private fun saveSettings() {
prefsManager.preferences.let {
it.scale =
- if (temperature_toggle.checkedRadioButtonId == R.id.celsius) TemperatureScale.CELSIUS
- else TemperatureScale.FAHRENHEIT
+ if (_binding.temperatureToggle.checkedRadioButtonId == R.id.celsius) TemperatureScale.CELSIUS
+ else TemperatureScale.FAHRENHEIT
prefsManager.savePreferences(it)
}
}
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 d48a0ed8..9dff7433 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
@@ -19,14 +19,12 @@ 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.databinding.ActivityMotionBinding
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.*
import timber.log.Timber
class MotionActivity : GdxActivity() {
@@ -35,12 +33,13 @@ class MotionActivity : GdxActivity() {
private var gdxAdapter: GdxAdapter? = null
private lateinit var viewModel: MotionViewModel
+ private lateinit var binding: ActivityMotionBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val view = LayoutInflater.from(this)
- .inflate(R.layout.activity_motion, null, false)
- mainSection?.addView(view)
+ binding = ActivityMotionBinding
+ .inflate(LayoutInflater.from(this), null, false)
+ mainSection?.addView(binding.root)
viewModel = ViewModelProvider(this).get(MotionViewModel::class.java)
setupClickListeners()
@@ -82,22 +81,23 @@ class MotionActivity : GdxActivity() {
private fun setAcceleration(x: Float, y: Float, z: Float) {
val accelerationString = getString(R.string.motion_acceleration_g)
- acceleration_x.text = String.format(accelerationString, x)
- acceleration_y.text = String.format(accelerationString, y)
- acceleration_z.text = String.format(accelerationString, z)
+ binding.motionDemoAccelerationParent.accelerationX.text = String.format(accelerationString, x)
+ binding.motionDemoAccelerationParent.accelerationY.text = String.format(accelerationString, y)
+ binding.motionDemoAccelerationParent.accelerationZ.text = String.format(accelerationString, z)
}
// Angles are measured in degrees (-180 to 180)
private fun setOrientation(x: Float, y: Float, z: Float) {
val degreeString = getString(R.string.motion_orientation_degree)
- orientation_x.text = String.format(degreeString, x)
- orientation_y.text = String.format(degreeString, y)
- orientation_z.text = String.format(degreeString, z)
+
+ binding.motionDemoOrientationParent.orientationX.text = String.format(degreeString, x)
+ binding.motionDemoOrientationParent.orientationY.text = String.format(degreeString, y)
+ binding.motionDemoOrientationParent.orientationZ.text = String.format(degreeString, z)
gdxAdapter?.setOrientation(x, y, z)
}
private fun setupClickListeners() {
- calibrate.setOnClickListener {
+ binding.calibrate .setOnClickListener {
popupCalibratingDialog()
Handler(Looper.getMainLooper()).postDelayed({
viewModel.calibrate(gatt)
@@ -134,8 +134,8 @@ class MotionActivity : GdxActivity() {
}
private fun setCalibrateVisible(enabled: Boolean) {
- calibrate.visibility =
- if (enabled) View.VISIBLE
+ binding.calibrate.visibility =
+ if (enabled) View.VISIBLE
else View.INVISIBLE
}
@@ -156,15 +156,19 @@ class MotionActivity : GdxActivity() {
useWakelock = false
}
val gdx3dView = initializeForView(gdxAdapter, config)
- car_animation.addView(gdx3dView)
+ binding.carAnimation .addView(gdx3dView)
}
@SuppressLint("MissingPermission")
private fun showBrokenSensorsMessage(brokenSensors: Set) {
AlertDialog.Builder(this).apply {
setTitle(getString(R.string.sensor_malfunction_dialog_title))
- setMessage(getString(R.string.critical_sensor_malfunction_dialog_message,
- TextUtils.join(", ", brokenSensors)))
+ setMessage(
+ getString(
+ R.string.critical_sensor_malfunction_dialog_message,
+ TextUtils.join(", ", brokenSensors)
+ )
+ )
setPositiveButton(getString(R.string.button_ok)) { _, _ ->
gatt?.disconnect() ?: onDeviceDisconnected()
}
@@ -201,9 +205,11 @@ class MotionActivity : GdxActivity() {
queueMotionNotificationsSetup()
}
- 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
@@ -215,14 +221,19 @@ class MotionActivity : GdxActivity() {
GattCharacteristic.ModelNumberString,
GattCharacteristic.BatteryLevel,
GattCharacteristic.PowerSource,
- GattCharacteristic.FirmwareRevision -> statusFragment.handleBaseCharacteristic(characteristic)
- else -> { }
+ GattCharacteristic.FirmwareRevision -> statusFragment.handleBaseCharacteristic(
+ characteristic
+ )
+
+ else -> {}
}
}
- override fun onCharacteristicWrite(gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- status: Int) {
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic,
+ status: Int
+ ) {
super.onCharacteristicWrite(gatt, characteristic, status)
if (status != BluetoothGatt.GATT_SUCCESS) return
@@ -230,20 +241,24 @@ class MotionActivity : GdxActivity() {
when (characteristic.value[0]) {
0x01.toByte() -> viewModel.resetOrientation(gatt, characteristic)
0x02.toByte() -> closeCalibratingDialog()
- else -> { }
+ 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.Acceleration -> {
val accelerationX = characteristic.getIntValue(gattCharacteristic.format, 0)
@@ -252,13 +267,19 @@ class MotionActivity : GdxActivity() {
Timber.d("Acceleration; X = $accelerationX, Y = $accelerationY, Z = $accelerationZ")
if (setup) {
- sensorChecker.checkIfMotionSensorBroken(ThunderboardSensor.Acceleration,
- accelerationX, accelerationY, accelerationZ)
+ sensorChecker.checkIfMotionSensorBroken(
+ ThunderboardSensor.Acceleration,
+ accelerationX, accelerationY, accelerationZ
+ )
}
- viewModel.acceleration.postValue(floatArrayOf(
- accelerationX / 1000f, accelerationY / 1000f, accelerationZ / 1000f))
+ viewModel.acceleration.postValue(
+ floatArrayOf(
+ accelerationX / 1000f, accelerationY / 1000f, accelerationZ / 1000f
+ )
+ )
}
+
GattCharacteristic.Orientation -> {
val orientationX = characteristic.getIntValue(gattCharacteristic.format, 0)
val orientationY = characteristic.getIntValue(gattCharacteristic.format, 2)
@@ -266,8 +287,10 @@ class MotionActivity : GdxActivity() {
Timber.d("Orientation; X = $orientationX, Y = $orientationY, Z = $orientationZ")
if (setup) {
- sensorChecker.checkIfMotionSensorBroken(ThunderboardSensor.Orientation,
- orientationX, orientationY, orientationZ)
+ sensorChecker.checkIfMotionSensorBroken(
+ ThunderboardSensor.Orientation,
+ orientationX, orientationY, orientationZ
+ )
val brokenSensors = sensorChecker.motionSensors.filter {
it.value == SensorChecker.SensorState.BROKEN
}.keys
@@ -280,21 +303,31 @@ class MotionActivity : GdxActivity() {
}
}
- viewModel.orientation.postValue(floatArrayOf(
- orientationX / 100f, orientationY / 100f, orientationZ / 100f))
+ viewModel.orientation.postValue(
+ floatArrayOf(
+ orientationX / 100f, orientationY / 100f, orientationZ / 100f
+ )
+ )
}
+
GattCharacteristic.Calibration -> {
when (characteristic.value[1]) {
- 0x01.toByte() -> viewModel.resetOrientation(gatt, characteristic) /* Somehow needed for properly resetting char's value */
- else -> { }
+ 0x01.toByte() -> viewModel.resetOrientation(
+ gatt,
+ characteristic
+ ) /* Somehow needed for properly resetting char's value */
+ else -> {}
}
}
- else -> { }
+
+ else -> {}
}
}
- 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()
}
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 0dafd412..f6d21143 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
@@ -200,6 +200,8 @@ class WifiCommissioningActivity : BaseDemoActivity() {
}
BluetoothService.GattConnectType.DEV_KIT_SENSOR -> {
+ // println("--------------Connected${connectedAccessPoint!!.ipAddress}")
+ // println("--------------Connected${clickedAccessPoint!!.ipAddress}")
val devKitIntent = Intent(
this,
DevKitSensor917Activity::class.java
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_commissioning/adapters/AccessPointsAdapter.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_commissioning/adapters/AccessPointsAdapter.kt
index 23ca6088..8147a0c1 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_commissioning/adapters/AccessPointsAdapter.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_commissioning/adapters/AccessPointsAdapter.kt
@@ -17,13 +17,13 @@ import java.util.*
* Created by harika on 18-04-2016.
*/
class AccessPointsAdapter(
- private val accessPoints: ArrayList,
- private val listener: OnItemClickListener
+ private val accessPoints: ArrayList,
+ private val listener: OnItemClickListener
) : RecyclerView.Adapter() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AccessPointViewHolder {
val itemView = LayoutInflater.from(parent.context)
- .inflate(R.layout.adapter_access_point, parent, false)
+ .inflate(R.layout.adapter_access_point, parent, false)
return AccessPointViewHolder(itemView)
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/AlertErrorDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/AlertErrorDialog.kt
index 49e69cb6..96b7b4fc 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/AlertErrorDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/AlertErrorDialog.kt
@@ -7,23 +7,29 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_error.*
+import com.siliconlabs.bledemo.databinding.DialogAlertErrorBinding
+
class AlertErrorDialog(
private val otaErrorCallback: OtaErrorCallback
) : BaseDialogFragment(
- hasCustomWidth = true,
- isCanceledOnTouchOutside = false
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = false
) {
+ private lateinit var binding: DialogAlertErrorBinding
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_alert_error, container, false)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogAlertErrorBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
-
- btn_ok.setOnClickListener {
+ binding.btnOk.setOnClickListener {
dismiss()
otaErrorCallback.onDismiss()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaFileSelectionDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaFileSelectionDialog.kt
index 648b5f07..0f4558e3 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaFileSelectionDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaFileSelectionDialog.kt
@@ -7,18 +7,22 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.databinding.DialogWifiOtaFileUpdateBinding
-import kotlinx.android.synthetic.main.dialog_ota_file_selection_iop.ota_cancel
-class WiFiOtaFileSelectionDialog(private val cancelCallback: CancelCallback,
- private val listener: FileSelectionListener, private val ipAddress: String?) : BaseDialogFragment(
- hasCustomWidth = true,
- isCanceledOnTouchOutside = false
+
+class WiFiOtaFileSelectionDialog(
+ private val cancelCallback: CancelCallback,
+ private val listener: FileSelectionListener, private val ipAddress: String?
+) : BaseDialogFragment(
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = false
) {
private lateinit var _binding: DialogWifiOtaFileUpdateBinding
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View? {
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
_binding = DialogWifiOtaFileUpdateBinding.inflate(inflater)
_binding.wifiIpAddress.text = ipAddress
return _binding.root
@@ -27,7 +31,7 @@ class WiFiOtaFileSelectionDialog(private val cancelCallback: CancelCallback,
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupUiListeners()
- ota_cancel.setOnClickListener {
+ _binding.otaCancel.setOnClickListener {
dismiss()
cancelCallback.onDismiss()
}
@@ -49,6 +53,7 @@ class WiFiOtaFileSelectionDialog(private val cancelCallback: CancelCallback,
fun checkPortNumberValid(): Boolean {
return _binding.portId.text.length >= 4
}
+
fun changeFileName(newName: String?) {
_binding.selectAppFileBtn.text = newName
}
@@ -61,7 +66,7 @@ class WiFiOtaFileSelectionDialog(private val cancelCallback: CancelCallback,
_binding.otaProceed.isEnabled = false
}
- fun getPortId() : String {
+ fun getPortId(): String {
return _binding.portId.text.toString()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/activities/WifiThroughputActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/activities/WifiThroughputActivity.kt
new file mode 100644
index 00000000..383f14d7
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/activities/WifiThroughputActivity.kt
@@ -0,0 +1,436 @@
+package com.siliconlabs.bledemo.features.demo.wifi_throughput.activities
+
+import android.content.Context
+import android.net.InetAddresses
+import android.net.wifi.WifiManager
+import android.os.Build
+import android.os.Bundle
+import android.util.Patterns
+import android.view.MenuItem
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material.Button
+import androidx.compose.material.ButtonDefaults
+import androidx.compose.material.Card
+import androidx.compose.material.ExperimentalMaterialApi
+import androidx.compose.material.Text
+import androidx.compose.material.TextButton
+import androidx.compose.material.TextField
+import androidx.compose.material.TextFieldDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.Dialog
+import androidx.compose.ui.window.DialogProperties
+import androidx.fragment.app.Fragment
+import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.ActivityWifiThroughputBinding
+import com.siliconlabs.bledemo.features.demo.wifi_throughput.fragments.WifiThroughPutDetailScreen
+import com.siliconlabs.bledemo.features.demo.wifi_throughput.utils.ThroughputUtils
+import com.siliconlabs.bledemo.features.iop_test.utils.Utils
+import java.net.InetAddress
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+
+class WifiThroughputActivity : AppCompatActivity() {
+
+ private lateinit var binding: ActivityWifiThroughputBinding
+ private val throughPutDemos = ThroughputUtils.WiFiThroughPutFeature.values()
+ private lateinit var context: Context
+ private var isConfirmCalled = mutableStateOf(false)
+ var ipAddress by mutableStateOf("")
+ var portNumber by mutableStateOf("")
+ var userSelectedFeature: Int by mutableIntStateOf(0)
+ private var isDownload = mutableStateOf(false)
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ context = this@WifiThroughputActivity
+ binding = ActivityWifiThroughputBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ findViewById(R.id.my_composable).setContent {
+ GridLayout(this, throughPutDemos)
+ val isConfirm = remember { isConfirmCalled }
+ if (isConfirm.value) {
+ //FragmentContainer()
+ }
+ }
+
+ //setSupportActionBar(binding.toolbar)
+ val actionBar = supportActionBar
+ actionBar!!.setHomeAsUpIndicator(R.drawable.matter_back)
+ actionBar.setDisplayHomeAsUpEnabled(true)
+ actionBar.setTitle(R.string.wifi_title_Throughput)
+ }
+
+ // Function to update the ActionBar title
+ fun updateActionBarTitle(title: String) {
+ supportActionBar?.title = title
+ }
+
+ // Function to reset the title back to the static one
+ fun resetActionBarTitle() {
+ supportActionBar?.title = getString(R.string.wifi_title_Throughput)
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ return when (item.itemId) {
+ android.R.id.home -> {
+ onBackPressed()
+ true
+ }
+
+ else -> super.onOptionsItemSelected(item)
+ }
+ }
+
+ override fun onBackPressed() {
+ resetActionBarTitle()
+ val myFragment: WifiThroughPutDetailScreen? =
+ supportFragmentManager.findFragmentByTag("tag") as WifiThroughPutDetailScreen?
+ if (myFragment != null && myFragment.isVisible()) {
+ supportFragmentManager.popBackStack()
+ }
+ super.onBackPressed()
+ }
+
+ private fun showThroughputDetailScreen(
+ userSelectedOption: Int,
+ ipAddress: String,
+ portNumber: String
+ ) {
+ val mBundle = Bundle()
+ mBundle.putString(
+ ThroughputUtils.throughPutType,
+ ThroughputUtils.getTitle(userSelectedOption, context)
+ )
+ mBundle.putString(ThroughputUtils.ipAddress, ipAddress)
+ mBundle.putString(ThroughputUtils.portNumber, portNumber)
+ val fragment = WifiThroughPutDetailScreen()
+ showFragment(
+ fragment,
+ mBundle,
+ fragment::class.java.simpleName
+ )
+ }
+
+ private fun showFragment(
+ fragment: Fragment, bundle: Bundle, tag: String? = null,
+ ) {
+ val fManager = supportFragmentManager
+ val fTransaction = fManager.beginTransaction()
+ fragment.setArguments(bundle)
+
+ fTransaction.add(binding.throughputContainer, fragment, tag)
+ .addToBackStack(null)
+ .commit()
+
+ }
+
+ @OptIn(ExperimentalMaterialApi::class)
+ @Composable
+ fun GridLayout(
+ context: Context,
+ throughPutDemos: Array
+ ) {
+ val dialogState: MutableState = remember {
+ mutableStateOf(false)
+ }
+ val dialogHeaderTitle: MutableState = remember { mutableStateOf("") }
+ val dialogHeaderSubTitle: MutableState = remember { mutableStateOf("") }
+ LazyVerticalGrid(columns = GridCells.Fixed(2),
+ contentPadding = PaddingValues(
+ start = 12.dp,
+ top = 16.dp,
+ end = 12.dp,
+ bottom = 16.dp
+ ),
+ content = {
+ items(throughPutDemos.size) {
+ Card(
+ backgroundColor = colorResource(R.color.silabs_white),
+ shape = RoundedCornerShape(8.dp),
+ modifier = Modifier
+ .padding(4.dp)
+ .size(150.dp)
+ .fillMaxWidth(),
+ elevation = 8.dp,
+ onClick = {
+ dialogState.value = true
+ if (ThroughputUtils.getTitle(
+ it,
+ context
+ ) == ThroughputUtils.THROUGHPUT_TYPE_TCP_DOWNLOAD
+ ) {
+ dialogHeaderTitle.value = getString(R.string.tcp_server)
+ dialogHeaderSubTitle.value =
+ getString(R.string.tcp_download_sub_title)
+ } else if (ThroughputUtils.getTitle(
+ it,
+ context
+ ) == ThroughputUtils.THROUGHPUT_TYPE_TCP_UPLOAD
+ ) {
+ dialogHeaderTitle.value = getString(R.string.tcp_client)
+ dialogHeaderSubTitle.value =
+ getString(R.string.tcp_upload_sub_title)
+ } else if (ThroughputUtils.getTitle(
+ it,
+ context
+ ) == ThroughputUtils.THROUGHPUT_TYPE_UDP_DOWNLOAD
+ ) {
+ dialogHeaderTitle.value = getString(R.string.udp_server)
+ dialogHeaderSubTitle.value =
+ getString(R.string.dialog_udp_download_sub_title)
+ } else if (ThroughputUtils.getTitle(
+ it,
+ context
+ ) == ThroughputUtils.THROUGHPUT_TYPE_UDP_UPLOAD
+ ) {
+ dialogHeaderTitle.value = getString(R.string.udp_client)
+ dialogHeaderSubTitle.value =
+ getString(R.string.dialog_udp_upload_sub_title)
+ } else if (ThroughputUtils.getTitle(
+ it,
+ context
+ ) == ThroughputUtils.THROUGHPUT_TYPE_TLS_DOWNLOAD
+ ) {
+ dialogHeaderTitle.value = getString(R.string.tls_server)
+ dialogHeaderSubTitle.value =
+ getString(R.string.dialog_tls_download_sub_title)
+ } else if (ThroughputUtils.getTitle(
+ it,
+ context
+ ) == ThroughputUtils.THROUGHPUT_TYPE_TLS_UPLOAD
+ ) {
+ dialogHeaderTitle.value = getString(R.string.tls_server)
+ dialogHeaderSubTitle.value =
+ getString(R.string.dialog_sub_title_tls_upload)
+ }
+ userSelectedFeature = it
+ if (ThroughputUtils.isThroughPutTypeDownload(it)) {
+ isDownload.value = false
+ ipAddress = getLocalIpAddress(context)
+ } else {
+ isDownload.value = true
+ ipAddress = ""
+ }
+ }
+ ) {
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier.fillMaxSize()
+ ) {
+ Text(
+ text = ThroughputUtils.getTitle(it, context),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+ fontFamily = FontFamily.SansSerif,
+ color = colorResource(id = R.color.silabs_black),
+ textAlign = TextAlign.Center,
+ modifier = Modifier.padding(16.dp)
+ )
+ }
+
+ }
+ }
+ })
+
+ if (dialogState.value) {
+ Dialog(
+ onDismissRequest = ({
+ dialogState.value = false
+ isConfirmCalled.value = false
+ }),
+ properties = DialogProperties(
+ dismissOnBackPress = true,
+ dismissOnClickOutside = false
+ )
+ ) {
+ Card(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(450.dp)
+ .padding(16.dp),
+ shape = RoundedCornerShape(16.dp),
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxSize(),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Text(
+ text = dialogHeaderTitle.value,
+ fontWeight = FontWeight.Black,
+ fontSize = 22.sp,
+ fontFamily = FontFamily.SansSerif,
+ color = colorResource(id = R.color.silabs_black),
+ textAlign = TextAlign.Center,
+ modifier = Modifier.padding(16.dp),
+ )
+ Text(
+ text = dialogHeaderSubTitle.value,
+ fontSize = 16.sp,
+ fontFamily = FontFamily.SansSerif,
+ fontWeight = FontWeight.Medium,
+ color = colorResource(id = R.color.silabs_primary_text),
+ modifier = Modifier
+ .padding(16.dp)
+ .fillMaxWidth(),
+ )
+ TextField(
+ textStyle = TextStyle(fontSize = 20.sp),
+ modifier = Modifier.padding(16.dp),
+ enabled = isDownload.value,
+ value = ipAddress,
+ onValueChange = {
+ if (it.length <= 15) {
+ ipAddress = it
+ }
+
+ },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
+ label = { Text(stringResource(R.string.enter_ip_address)) },
+ colors = TextFieldDefaults.textFieldColors(
+ unfocusedLabelColor = colorResource(R.color.silabs_black),
+ focusedLabelColor = colorResource(R.color.silabs_dark_blue),
+ textColor = colorResource(R.color.silabs_black), // Text color
+ backgroundColor = Color.LightGray, // Background color
+ placeholderColor = Color.Gray, // Placeholder text color
+ cursorColor = colorResource(R.color.silabs_dark_blue), // Cursor color
+ focusedIndicatorColor = colorResource(R.color.silabs_dark_blue), // Focused indicator color
+ unfocusedIndicatorColor = colorResource(id = R.color.silabs_dark_gray_text) // Unfocused indicator color
+ )
+ )
+
+ val maxChar = 4
+ TextField(
+ textStyle = TextStyle(fontSize = 20.sp),
+ modifier = Modifier.padding(16.dp),
+ value = portNumber,
+ onValueChange = {
+ if (it.length <= maxChar)
+ portNumber = it
+ },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
+ label = {
+ Text(context.getString(R.string.enter_port_number))
+ },
+ colors = TextFieldDefaults.textFieldColors(
+ unfocusedLabelColor = colorResource(R.color.silabs_black),
+ focusedLabelColor = colorResource(R.color.silabs_dark_blue),
+ textColor = colorResource(R.color.silabs_black), // Text color
+ backgroundColor = Color.LightGray, // Background color
+ placeholderColor = Color.Gray, // Placeholder text color
+ cursorColor = colorResource(R.color.silabs_dark_blue), // Cursor color
+ focusedIndicatorColor = colorResource(R.color.silabs_dark_blue), // Focused indicator color
+ unfocusedIndicatorColor = colorResource(id = R.color.silabs_dark_gray_text) // Unfocused indicator color
+ )
+ )
+
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center,
+ ) {
+ TextButton(
+ onClick = {
+ dialogState.value = false
+ isConfirmCalled.value = false
+ },
+ modifier = Modifier.padding(8.dp),
+ ) {
+ Text(
+ text = context.getString(R.string.matter_cancel),
+ color = colorResource(id = R.color.silabs_dark_blue),
+ fontSize = 18.sp
+ )
+ }
+
+ var isValidIp = false
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ isValidIp = InetAddresses.isNumericAddress(ipAddress)
+ } else {
+ isValidIp = Patterns.IP_ADDRESS.matcher(ipAddress).matches()
+ }
+ Button(
+ onClick = {
+ if (/*isValidIp
+ && */portNumber.length >= maxChar) {
+ dialogState.value = false
+ showThroughputDetailScreen(
+ userSelectedFeature,
+ ipAddress,
+ portNumber
+ )
+ isConfirmCalled.value = true
+ } else {
+ Toast.makeText(
+ context,
+ getString(R.string.please_enter_valid_port_number),
+ Toast.LENGTH_LONG
+ ).show()
+ }
+ },
+ shape = RoundedCornerShape(8.dp), // Rounded corners with a 16 dp radius
+ colors = ButtonDefaults.buttonColors(colorResource(R.color.silabs_dark_blue)),
+ modifier = Modifier.padding(8.dp)
+ ) {
+ Text(
+ text = context.getString(R.string.dialog_start_server),
+ color = Color.White,
+ fontSize = 18.sp
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ private fun getLocalIpAddress(context: Context): String {
+ val wifiManager =
+ (context.getSystemService(Context.WIFI_SERVICE) as WifiManager)
+ val wifiInfo = wifiManager.connectionInfo
+ val ipInt = wifiInfo.ipAddress
+ return InetAddress.getByAddress(
+ ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ipInt).array()
+ ).hostAddress
+ }
+}
+
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/adapter/WifiThroughputAdapter.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/adapter/WifiThroughputAdapter.kt
new file mode 100644
index 00000000..c32a3ee5
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/adapter/WifiThroughputAdapter.kt
@@ -0,0 +1,65 @@
+package com.siliconlabs.bledemo.features.demo.wifi_throughput.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.features.demo.wifi_throughput.model.WifiThroughputData
+
+class WifiThroughputAdapter(private val list: MutableList) : RecyclerView.Adapter() {
+ val myData = mutableListOf()
+
+ fun submitList(newData: MutableList) {
+ myData.clear()
+ myData.addAll(newData)
+ notifyDataSetChanged()
+ }
+
+ /**
+ * Provide a reference to the type of views that you are using
+ * (custom ViewHolder)
+ */
+ class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
+ val interval_tv: TextView
+ val transfer_rate_tv: TextView
+ val bandwidth_rate_tv: TextView
+
+ init {
+ // Define click listener for the ViewHolder's View
+ interval_tv = view.findViewById(R.id.interval)
+ transfer_rate_tv = view.findViewById(R.id.transfer_rate)
+ bandwidth_rate_tv = view.findViewById(R.id.bandwidth)
+
+ }
+ }
+
+ override fun onCreateViewHolder(
+ viewGroup: ViewGroup,
+ viewType: Int
+ ): ViewHolder {
+ val view = LayoutInflater.from(viewGroup.context)
+ .inflate(R.layout.wifi_throughput_log_row, viewGroup, false)
+
+ return ViewHolder(view)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ // Get element from your dataset at this position and replace the
+ // contents of the view with that element
+ val throughPutValues = myData.get(position).split(",").toTypedArray()
+
+ holder.interval_tv.text = throughPutValues.get(0)
+ holder.transfer_rate_tv.text = throughPutValues.get(1)
+ holder.bandwidth_rate_tv.text = "${throughPutValues.get(2)} Mbits/sec"
+ /* holder.transfer_rate_tv.visibility = View.GONE
+ holder.bandwidth_rate_tv.visibility = View.GONE*/
+
+ }
+
+ override fun getItemCount(): Int {
+ return myData.size
+ }
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/fragments/WifiThroughPutDetailScreen.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/fragments/WifiThroughPutDetailScreen.kt
new file mode 100644
index 00000000..e780dfcf
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/fragments/WifiThroughPutDetailScreen.kt
@@ -0,0 +1,335 @@
+package com.siliconlabs.bledemo.features.demo.wifi_throughput.fragments
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.text.Html
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.core.text.HtmlCompat
+import androidx.core.view.isVisible
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.transition.Visibility
+import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.FragmentWifiThroughPutDetailScreenBinding
+import com.siliconlabs.bledemo.features.demo.throughput.views.SpeedView
+import com.siliconlabs.bledemo.features.demo.wifi_throughput.activities.WifiThroughputActivity
+import com.siliconlabs.bledemo.features.demo.wifi_throughput.adapter.WifiThroughputAdapter
+import com.siliconlabs.bledemo.features.demo.wifi_throughput.utils.ThroughputUtils
+import com.siliconlabs.bledemo.features.demo.wifi_throughput.viewmodel.WifiThroughputViewModel
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class WifiThroughPutDetailScreen : Fragment() {
+ private var mBundle : Bundle? = null
+ private lateinit var binding: FragmentWifiThroughPutDetailScreenBinding
+
+ private val throughPutUnitsArray =
+ arrayListOf(
+ "0",
+ "12.5 Mbps",
+ "25 Mbps",
+ "37.5 Mbps",
+ "50 Mbps",
+ "62.5 Mbps",
+ "75 Mbps",
+ "87.5 Mbps",
+ "100 Mbps"
+ )
+ private val viewModel : WifiThroughputViewModel by viewModels()
+ var list: MutableList = mutableListOf()
+ var throughPutTestModeDownload = false
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ super.onCreateView(inflater, container, savedInstanceState)
+ // Inflate the layout for this fragment
+ binding = FragmentWifiThroughPutDetailScreenBinding.inflate(inflater, container, false)
+ binding.wifiSpeedView.setUnitsArray(throughPutUnitsArray)
+ binding.finalResultLl.visibility = View.GONE
+ binding.headers.visibility = View.GONE
+
+ mBundle = arguments
+
+
+ updateThroughPutSpeed()
+
+ binding.wifiTpMainLayout.setOnClickListener{
+ //Do nothing. It is to avoid background touch.
+ }
+
+ viewModel.isConnceted()
+ .observe(viewLifecycleOwner) {
+ if (it){
+ binding.connectionStatus.visibility = View.GONE
+ }else{
+ binding.connectionStatus.visibility = View.VISIBLE
+ }
+ }
+
+ val customAdapter = WifiThroughputAdapter(list)
+ val recyclerView = binding.incrementalLog
+ recyclerView.layoutManager = LinearLayoutManager(requireContext())
+ recyclerView.adapter = customAdapter
+ viewModel.updateLogsPerSecond().observe(viewLifecycleOwner){
+ customAdapter.submitList(it)
+ recyclerView.visibility = View.VISIBLE
+ if (it.isNotEmpty()){
+ binding.headers.visibility = View.VISIBLE
+ recyclerView.smoothScrollToPosition(it.size - 1)
+ }
+ }
+
+ startThroughPutServer()
+
+ binding.start.setOnClickListener {
+ binding.finalResultLl.visibility = View.GONE
+ binding.headers.visibility = View.GONE
+ binding.start.isEnabled = false
+ startThroughPutServer()
+ }
+
+ binding.cancel.setOnClickListener {
+ //dialog?.dismiss()
+ viewModel.stop()
+ var fm : FragmentManager = requireActivity().supportFragmentManager
+ fm.popBackStack()
+ }
+
+ viewModel.updateFinalResult().observe(viewLifecycleOwner){
+ if (null != it && it.isNotEmpty()){
+ binding.wifiSpeedView.updateSpeed( getProgress(0f),
+ getSpeedAsString(0f),
+ getUnitAsString(0f),
+ getTestMode())
+ binding.start.isEnabled = true
+ binding.finalResultLl.visibility = View.VISIBLE
+ if (throughPutTestModeDownload){
+ val finalBytesSent = "${getString(R.string.total_bytes_received)}: ${it.get("transfer")}"
+ binding.finalBytesSent.text = Html.fromHtml(finalBytesSent,HtmlCompat.FROM_HTML_MODE_LEGACY)
+ }else{
+ val totalBytesSent = "${getString(R.string.total_bytes_sent)}: ${it.get("transfer")}"
+ binding.finalBytesSent.text = Html.fromHtml(totalBytesSent,HtmlCompat.FROM_HTML_MODE_LEGACY)
+ }
+ val throughPutAchieved = "${getString(R.string.throughput_achieved)}: @ ${it.get("bandwidth")} ${getString(R.string.mbps_in_30_successfully)}"
+ binding.finalAcheievedBandvidth.text = Html.fromHtml(throughPutAchieved,HtmlCompat.FROM_HTML_MODE_LEGACY)
+ }
+ }
+
+ viewModel.handleException().observe(viewLifecycleOwner){
+ if (it){
+ binding.start.isEnabled = true
+ recyclerView.visibility = View.GONE
+ // binding.finalResultLl.visibility = View.GONE
+ Toast.makeText(context,
+ getString(R.string.connection_couldn_t_be_established), Toast.LENGTH_LONG).show()
+ viewModel.stop()
+ requireActivity().supportFragmentManager.popBackStack()
+ (activity as? WifiThroughputActivity)?.updateActionBarTitle(requireContext().getString(R.string.wifi_title_Throughput))
+ }
+ }
+
+ viewModel.handleTlsZeroBytes().observe(viewLifecycleOwner){
+ if (it){
+ binding.start.isEnabled = true
+ recyclerView.visibility = View.GONE
+ // binding.finalResultLl.visibility = View.GONE
+ Toast.makeText(context,
+ getString(R.string.ensure_right_combination_of_fw_is_flashed), Toast.LENGTH_LONG).show()
+ viewModel.stop()
+ requireActivity().supportFragmentManager.popBackStack()
+ (activity as? WifiThroughputActivity)?.updateActionBarTitle(requireContext().getString(R.string.wifi_title_Throughput))
+ }
+ }
+
+ return binding.root
+ }
+
+ private fun startThroughPutServer() {
+ viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
+ mBundle?.let {
+ if (it.getString(ThroughputUtils.throughPutType)?.equals(
+ ThroughputUtils.THROUGHPUT_TYPE_TCP_UPLOAD,
+ ignoreCase = true
+ ) == true
+ ) {
+ throughPutTestModeDownload = false
+ //set the actionBar title
+ (activity as? WifiThroughputActivity)?.updateActionBarTitle(it.getString(ThroughputUtils.throughPutType).toString())
+ binding.connectionStatus.visibility = View.VISIBLE
+ if(binding.connectionStatus.isVisible){
+ binding.connectionStatusTv.text = getString(R.string.waiting_for_client_to_connect)
+ }
+ viewModel.tcpClient(
+ it.getString(ThroughputUtils.ipAddress)!!,
+ it.getString(ThroughputUtils.portNumber)!!.toInt()
+ )
+ } else if (it.getString(ThroughputUtils.throughPutType)?.equals(
+ ThroughputUtils.THROUGHPUT_TYPE_TCP_DOWNLOAD,
+ ignoreCase = true
+ ) == true
+ ) {
+ //set the actionBar title
+ (activity as? WifiThroughputActivity)?.updateActionBarTitle(it.getString(ThroughputUtils.throughPutType).toString())
+ throughPutTestModeDownload = true
+ binding.connectionStatus.visibility = View.VISIBLE
+ if(binding.connectionStatus.isVisible){
+ binding.connectionStatusTv.text = getString(R.string.wifi_throughput_connecting_status)
+ }
+
+ viewModel.tcpServer(it.getString(ThroughputUtils.portNumber)!!.toInt())
+ } else if (it.getString(ThroughputUtils.throughPutType)?.equals(
+ ThroughputUtils.THROUGHPUT_TYPE_UDP_UPLOAD,
+ ignoreCase = true
+ ) == true
+ ) {
+ //set the actionBar title
+ (activity as? WifiThroughputActivity)?.updateActionBarTitle(it.getString(ThroughputUtils.throughPutType).toString())
+ throughPutTestModeDownload = false
+ binding.connectionStatus.visibility = View.VISIBLE
+ if(binding.connectionStatus.isVisible){
+ binding.connectionStatusTv.text = getString(R.string.waiting_for_client_to_connect)
+ binding.connectionStatusTv.visibility = View.GONE
+ }
+
+ viewModel.udpClient(
+ it.getString(ThroughputUtils.ipAddress)!!,
+ it.getString(ThroughputUtils.portNumber)!!.toInt()
+ )
+ } else if (it.getString(ThroughputUtils.throughPutType)?.equals(
+ ThroughputUtils.THROUGHPUT_TYPE_UDP_DOWNLOAD,
+ ignoreCase = true
+ ) == true
+ ) {
+ //set the actionBar title
+ (activity as? WifiThroughputActivity)?.updateActionBarTitle(it.getString(ThroughputUtils.throughPutType).toString())
+ throughPutTestModeDownload = true
+ binding.connectionStatus.visibility = View.VISIBLE
+ if(binding.connectionStatus.isVisible){
+ binding.connectionStatusTv.text = getString(R.string.wifi_throughput_connecting_status)
+ //binding.connectionStatusTv.visibility = View.GONE
+ }
+
+ viewModel.udpServer(it.getString(ThroughputUtils.portNumber)!!.toInt())
+ //ThroughputUtils.receiUDP()
+ } else if (it.getString(ThroughputUtils.throughPutType)?.equals(
+ ThroughputUtils.THROUGHPUT_TYPE_TLS_UPLOAD,
+ ignoreCase = true
+ ) == true
+ ) {
+ //set the actionBar title
+ (activity as? WifiThroughputActivity)?.updateActionBarTitle(it.getString(ThroughputUtils.throughPutType).toString())
+ throughPutTestModeDownload = false
+ binding.connectionStatus.visibility = View.VISIBLE
+ if(binding.connectionStatus.isVisible){
+ binding.connectionStatusTv.text = getString(R.string.waiting_for_client_to_connect)
+ }
+
+ viewModel.startTLSServer(
+ it.getString(ThroughputUtils.portNumber)!!.toInt(),
+ requireContext(),
+ true
+ )
+ } else if (it.getString(ThroughputUtils.throughPutType)?.equals(
+ ThroughputUtils.THROUGHPUT_TYPE_TLS_DOWNLOAD,
+ ignoreCase = true
+ ) == true
+ ) {
+ //set the actionBar title
+ (activity as? WifiThroughputActivity)?.updateActionBarTitle(it.getString(ThroughputUtils.throughPutType).toString())
+ throughPutTestModeDownload = true
+ binding.connectionStatus.visibility = View.VISIBLE
+ if(binding.connectionStatus.isVisible){
+ binding.connectionStatusTv.text = getString(R.string.waiting_for_client_to_connect)
+ }
+
+ viewModel.startTLSServer(
+ it.getString(ThroughputUtils.portNumber)!!.toInt(),
+ requireContext(),
+ false
+ )
+ } else {
+ /* Toast.makeText(requireContext(), "Working in progress", Toast.LENGTH_LONG)
+ .show()*/
+ }
+ }
+ }
+ }
+
+ private fun updateThroughPutSpeed() {
+ lifecycleScope.launch {
+ withContext(Dispatchers.Main) {
+ viewModel.updateSpeed()
+ .observe(viewLifecycleOwner) {
+ if (it.toString().equals("Infinity", ignoreCase = true) || it.toString()
+ .equals("Nan", ignoreCase = true)
+ )
+ return@observe
+
+
+ binding.wifiSpeedView.updateSpeed(
+ getWifiThroughPutProgress(it),
+ getSpeedAsString(it),
+ getUnitAsString(it),
+ getTestMode()
+ )
+ }
+ }
+ }
+ }
+
+ private fun getProgress(speed: Float):Int {
+ //println("Speed : $speed")
+ return ((speed / 20.0) * 100).toInt()
+
+ // return (speed / 20.0).toInt()
+ }
+
+ private fun getWifiThroughPutProgress(speed: Float):Int {
+ return ((speed / 100.0) * 100).toInt()
+ }
+
+ private fun getSpeedAsString(speed: Float): String {
+ /* return if (speed >= 1000000) {
+ (speed / 1000000.0).toString()
+ } else {
+ (speed / 100.0).toString()
+ }*/
+ //println("Speed getSpeedAsString : $speed")
+
+ return String.format("%.2f", speed)
+ }
+
+ private fun getUnitAsString(speed: Float): String {
+ /*return if (speed >= 1000000) {
+ "Mbps"
+ } else {
+ "kbps"
+ }*/
+ return "Mbps"
+ }
+
+ private fun getTestMode(): SpeedView.Mode {
+ if (throughPutTestModeDownload){
+ return SpeedView.Mode.DOWNLOAD
+ }
+ return SpeedView.Mode.UPLOAD
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ viewModel.stop()
+ }
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/model/WifiThroughputData.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/model/WifiThroughputData.kt
new file mode 100644
index 00000000..b952bdf7
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/model/WifiThroughputData.kt
@@ -0,0 +1,9 @@
+package com.siliconlabs.bledemo.features.demo.wifi_throughput.model
+
+data class WifiThroughputData(var seconds: String,
+ var transferRate: String,
+ var bandwidth:String){
+
+}
+
+
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/utils/ThroughputUtils.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/utils/ThroughputUtils.kt
new file mode 100644
index 00000000..5971bf89
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/utils/ThroughputUtils.kt
@@ -0,0 +1,248 @@
+package com.siliconlabs.bledemo.features.demo.wifi_throughput.utils
+
+import android.content.Context
+import com.siliconlabs.bledemo.R
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.net.DatagramPacket
+import java.net.DatagramSocket
+import java.net.InetAddress
+import java.net.InetSocketAddress
+import java.net.Socket
+import java.util.concurrent.TimeUnit
+
+
+object ThroughputUtils {
+
+ enum class WiFiThroughPutFeature(id: Int) {
+ TCP_RX(1),
+ TCP_TX(2),
+ UDP_RX(3),
+ UDP_TX(4),
+ TLS_RX(5),
+ TLS_TX(6)
+ }
+
+ var throughPutType : String = "throughputType"
+ var ipAddress : String = "ipAddress"
+ var portNumber : String = "portNumber"
+
+ const val THROUGHPUT_TYPE_TCP_UPLOAD = "TCP Upload"
+ const val THROUGHPUT_TYPE_UDP_UPLOAD = "UDP Upload"
+ const val THROUGHPUT_TYPE_TLS_UPLOAD = "TLS Upload"
+ const val THROUGHPUT_TYPE_TCP_DOWNLOAD = "TCP Download"
+ const val THROUGHPUT_TYPE_UDP_DOWNLOAD = "UDP Download"
+ const val THROUGHPUT_TYPE_TLS_DOWNLOAD = "TLS Download"
+
+
+ var port: Int = 5005
+ var running: Boolean = false
+ var socket: DatagramSocket? = null
+
+ fun getTitle(key : Int, context: Context) : String{
+ return when(key){
+ 0 -> context.getString(R.string.tcp_receive_title)
+ 1 -> context.getString(R.string.tcp_send_title)
+ 2 -> context.getString(R.string.udp_receive_title)
+ 3 -> context.getString(R.string.udp_send_title)
+ 4 -> context.getString(R.string.tls_receive_title)
+ 5 -> context.getString(R.string.tls_send_title)
+ else -> "Nothing"
+ }
+ }
+
+ fun isThroughPutTypeDownload(key : Int) : Boolean{
+ return when(key){
+ 0, 2, 4, 5 -> true
+ 1, 3 -> false
+ else -> false
+ }
+ }
+
+ fun sendEvent() {
+ val BYTES_TO_SEND = 536870912.0 //317470020// Example value, set your actual byte count
+ val UDP_BUFFER_SIZE = 1470 // Example buffer size, set accordingly
+ val TEST_TIMEOUT: Long = 10000 // Timeout in milliseconds
+ val dataBuffer = ByteArray(UDP_BUFFER_SIZE) // Example data buffer
+ val serverAddress: InetAddress
+ var socket: DatagramSocket? = null
+ var totalBytesSent = 0
+ var sentBytes: Int
+ var fail = 0
+ var pass = 0
+ val SEVER_IP = "192.168.1.194"
+ val buffer = ByteArray(1470)
+ for (i in buffer.indices) {
+ buffer[i] = ('A'.code + (i % 26)).toByte()
+ }
+ val startTime = System.nanoTime()
+
+ try {
+ serverAddress = InetAddress.getByName(SEVER_IP) // Replace with actual server address
+ socket = DatagramSocket()
+ socket.soTimeout = TEST_TIMEOUT.toInt()
+ val start = System.currentTimeMillis()
+
+ while (totalBytesSent < BYTES_TO_SEND) {
+ println("Total bytes sent so far : $totalBytesSent")
+ val packet = DatagramPacket(
+ buffer,
+ buffer.size,
+ serverAddress,
+ 5005
+ ) // Replace 9876 with actual server port
+ socket.send(packet)
+ val now = System.currentTimeMillis()
+
+ if ((now - start) > TEST_TIMEOUT) {
+ println(
+ """
+ Time Out: ${now - start}
+ """.trimIndent()
+ )
+ break
+ }
+ sentBytes = packet.length
+ if (sentBytes < 0) {
+ fail++
+ } else {
+ pass++
+ }
+ if (sentBytes > 0) {
+ totalBytesSent += sentBytes
+ }
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ } finally {
+ if (socket != null && !socket.isClosed) {
+ socket.close()
+ }
+ }
+ val endTime = System.nanoTime()
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ val bandwidthInMbps = (totalBytesSent * 8.0) / timeTakenInSeconds / 1_000_000
+ println("Bandwidth: $bandwidthInMbps Mbps")
+ /*println("Total Bytes Sent: $totalBytesSent")
+ println("Pass: $pass")
+ println("Fail: $fail")*/
+ }
+
+ fun receiveUDPData() {
+ val LISTENING_PORT = 5005 // Replace with actual listening port
+ val TEST_TIMEOUT = longArrayOf(60000) // Timeout in milliseconds
+ val hasDataReceived = booleanArrayOf(false)
+ val bytesRead = longArrayOf(0)
+ val start: Long
+ val now: Long
+ var serverSocket: DatagramSocket? = null
+ try {
+ serverSocket = DatagramSocket()
+ println(
+ """
+
+ Socket ID: ${serverSocket.localPort}
+ """.trimIndent()
+ )
+ //System.out.println("\nListening on Local Port " + LISTENING_PORT);
+ start = System.currentTimeMillis()
+ serverSocket.reuseAddress = true
+ if (!serverSocket.isBound) serverSocket.bind(InetSocketAddress(5005))
+
+ val finalServerSocket: DatagramSocket = serverSocket
+ val receiverThread = Thread {
+ val receiveBuffer =
+ ByteArray(1470) // Adjust buffer size as needed
+ while (!hasDataReceived[0]) {
+ try {
+ val receivePacket =
+ DatagramPacket(receiveBuffer, receiveBuffer.size)
+ finalServerSocket.receive(receivePacket)
+ bytesRead[0] += receivePacket.length.toLong()
+ hasDataReceived[0] =
+ true // Assuming we stop after first receive for simplicity
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+ }
+ receiverThread.start()
+ receiverThread.join(TEST_TIMEOUT[0])
+ now = System.currentTimeMillis()
+ println("\nUDP_RX Async Throughput test finished")
+ println(
+ """
+
+ Total bytes received: ${bytesRead[0]}
+ """.trimIndent()
+ )
+ measureAndPrintThroughput(bytesRead[0], (now - start))
+ } catch (e: IOException) {
+ e.printStackTrace()
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ } finally {
+ /*if (serverSocket != null && !serverSocket.isClosed()) {
+ serverSocket.close();
+ }*/
+ }
+ }
+
+ private fun measureAndPrintThroughput(totalBytesReceived: Long, duration: Long) {
+ val throughput = (totalBytesReceived / duration.toDouble()) * 1000 // bytes per second
+ println("Throughput: $throughput bytes/sec")
+ }
+
+ fun receiUDP() {
+ running = true
+ var totalBytesReceived =0L
+
+ Thread {
+ try {
+ var now: Long
+ socket = DatagramSocket(port)
+ val start = System.currentTimeMillis()
+
+ println("UDP Server started on port $port")
+
+ val buffer = ByteArray(1470)
+ while (running) {
+ val packet = DatagramPacket(buffer, buffer.size)
+ socket!!.receive(packet)
+ totalBytesReceived += packet.length
+ println(
+ "Total packets receieved is : $totalBytesReceived"
+ )
+ val data =
+ String(packet.data, 0, packet.length)
+ /* println(
+ "Received: " + data + " from " + packet.address.hostAddress
+ )*/
+ now = System.currentTimeMillis()
+
+ measureAndPrintThroughput(packet.length.toLong(), (now - start))
+ // Process the received data and send a response if needed
+ val response = "Echo: $data"
+ val responsePacket = DatagramPacket(
+ response.toByteArray(),
+ response.toByteArray().size,
+ packet.address,
+ packet.port
+ )
+ socket!!.send(responsePacket)
+ }
+ } catch (e: IOException) {
+ System.err.println("Error: " + e.message)
+ } finally {
+ if (socket != null) {
+ running = false
+ socket!!.close()
+ }
+ println("UDP Server stopped")
+ }
+ }.start()
+ }
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/viewmodel/WifiThroughputViewModel.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/viewmodel/WifiThroughputViewModel.kt
new file mode 100644
index 00000000..b6d1273c
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_throughput/viewmodel/WifiThroughputViewModel.kt
@@ -0,0 +1,720 @@
+package com.siliconlabs.bledemo.features.demo.wifi_throughput.viewmodel
+
+import android.content.Context
+import android.system.Os.socket
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.siliconlabs.bledemo.R
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import java.io.BufferedInputStream
+import java.io.DataInputStream
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.net.ConnectException
+import java.net.DatagramPacket
+import java.net.DatagramSocket
+import java.net.InetAddress
+import java.net.InetSocketAddress
+import java.net.ServerSocket
+import java.net.Socket
+import java.net.SocketTimeoutException
+import java.security.KeyStore
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.TimeUnit
+import javax.net.ssl.KeyManagerFactory
+import javax.net.ssl.SSLContext
+import javax.net.ssl.SSLServerSocket
+import javax.net.ssl.SSLServerSocketFactory
+
+
+class WifiThroughputViewModel : ViewModel() {
+ var bytesCountPerSec: Float = 0.0F
+ private var timerTask: TimerTask? = null
+ private var timer: Timer? = null
+ var count = -1
+ private val _updateSpeed = MutableLiveData()
+ private var finalThroughPut = 0
+ private var _perSecondLog = MutableLiveData>()
+ private var _updateFinalPackets = MutableLiveData>()
+ var finalBandwidth: Float = 0.0F
+ //Tcp Server
+ var totalBytesReceived = 0L
+ var running: Boolean = false
+ private var serverSocket: ServerSocket? = null
+ private val coroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
+ private var _handleException = MutableLiveData()
+ private var _tlsHandleZeroBytes = MutableLiveData()
+
+ private var isExceptionOccured = false
+ val mobileServerSocket = ServerSocket()
+ var isConncetedToClient = MutableLiveData()
+ var udpSocket = DatagramSocket()
+
+ init {
+ _perSecondLog.value = mutableListOf()
+ _updateFinalPackets.value = mutableMapOf()
+
+ }
+ fun updateSpeed():LiveData{
+ return _updateSpeed
+ }
+
+ fun updateLogsPerSecond():LiveData>{
+ return _perSecondLog
+ }
+
+ fun updateFinalResult(): LiveData>{
+ return _updateFinalPackets
+ }
+
+ fun handleException(): MutableLiveData {
+ return _handleException
+ }
+
+ fun handleTlsZeroBytes(): MutableLiveData{
+ return _tlsHandleZeroBytes
+ }
+
+ fun isConnceted(): MutableLiveData {
+ return isConncetedToClient
+ }
+
+ fun tcpClient(ipAddress : String, portNumber : Int){
+ println("TCP client started!!!")
+ isExceptionOccured = false
+ count = -1
+ finalThroughPut = 0
+ val TEST_TIMEOUT: Long = 30000 // Timeout in milliseconds
+ val BYTES_TO_SEND = 536870912.0 //317470020// Example value, set your actual byte count
+ val ip = ipAddress // Replace with your server's IP address
+ val port = portNumber // Replace with your server's port
+ val buffer = ByteArray(10240)
+ var socket : Socket? = null
+ var outputStream : OutputStream? = null
+ var inputStream : InputStream? = null
+ var totalBytesTransferred = 0L
+ var startTime = 0L
+ var start = 0L
+ var endTime : Long = 0
+ var isTimerStarted = false
+ try{
+ socket = Socket(ip, port)
+ socket.soTimeout = 30000
+
+ outputStream = socket.getOutputStream()
+ inputStream = socket.getInputStream()
+
+ while (totalBytesTransferred < BYTES_TO_SEND) {
+ if(!isTimerStarted){
+ isTimerStarted = true
+ startTime = System.nanoTime()
+ start = System.currentTimeMillis()
+ startTimer()
+ }
+
+ outputStream.write(buffer)
+ viewModelScope.launch(Dispatchers.Main) {
+ isConncetedToClient.value = true
+ }
+ totalBytesTransferred += buffer.size
+ addBytesToCount(buffer.size)
+
+ val now = System.currentTimeMillis()
+ if ((now - start) > TEST_TIMEOUT || count >= 30) {
+ println(
+ """
+ Time Out: ${now - start}
+ """.trimIndent()
+ )
+ break
+ }
+ }
+ endTime = System.nanoTime()
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ println("Time taken : " + timeTakenInSeconds)
+ val throughputInMbps =
+ (totalBytesTransferred * 8.0) / timeTakenInSeconds / 1_000_000
+ println("TCP Throughput total bytes : $totalBytesTransferred")
+
+ println("TCP Throughput: $throughputInMbps Mbps")
+
+ inputStream?.close()
+ outputStream?.close()
+ cancelTimer()
+ }catch (e: ConnectException){
+ endTime = System.nanoTime()
+ println("TCP Throughput: $e")
+ isExceptionOccured = true
+ cancelTimer()
+ } catch (e: Exception){
+ endTime = System.nanoTime()
+ println("TCP Throughput: $e")
+ //isExceptionOccured = true
+ pollTimeoutExceptionHandling(e)
+ cancelTimer()
+ }finally {
+ isTimerStarted = false
+ if(!isExceptionOccured){
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ val throughputInMbps =
+ (totalBytesTransferred * 8.0) / timeTakenInSeconds / 1_000_000
+ //val throughputInMbps = (totalBytesTransferred/(1024*1024)) / timeTakenInSeconds / 1_000_000
+ println("Time taken finally: " + timeTakenInSeconds)
+
+ println("TCP Throughput total bytes finally : $totalBytesTransferred")
+
+ println("TCP Throughput finally: $throughputInMbps Mbps")
+
+ socket?.close()
+ println("TCP Throughput finally : socket connection closed")
+ cancelTimer()
+ _updateFinalPackets.value?.put("transfer", totalBytesTransferred.toString())
+ _updateFinalPackets.value?.put("bandwidth", String.format("%.2f", throughputInMbps).toString())
+ viewModelScope.launch(Dispatchers.Main) {
+ _updateFinalPackets.value = _updateFinalPackets.value
+ }
+ _perSecondLog.value?.clear()
+ }else{
+ viewModelScope.launch(Dispatchers.Main) {
+ _handleException.value = isExceptionOccured
+ }
+ }
+ }
+
+ }
+
+ private inner class PeriodicSpeedUpdate : TimerTask() {
+ override fun run() {
+ count++
+ viewModelScope.launch(Dispatchers.Main) {
+ val throughputInMBps : Float = bytesCountPerSec//bytesToKB(bytesCountPerSec)
+ val bandwidth = ((bytesCountPerSec*8.388608)/(1000*1000)).toFloat()
+ finalBandwidth += bandwidth
+
+ var bandwidthPerSecondInString = bytesToHumanReadableSize(throughputInMBps)
+ var bandwidthPerSecond = ""
+
+ // removing duplicate whitespace
+ println("Extra whitespaces removed: "
+ + bandwidthPerSecondInString.replace("\\s+".toRegex(), " "))
+ // removing all the whitespaces
+ println("After removing all the whitespaces: "
+ + bandwidthPerSecondInString.replace("\\s+".toRegex(), ""))
+ if (bandwidthPerSecondInString.contains("kB", ignoreCase = true)){
+ println("After removing KB: "
+ + bandwidthPerSecondInString.replace("kB+".toRegex(), ""))
+
+ bandwidthPerSecond = String.format("%.2f", ((bandwidthPerSecondInString.replace("kB+".toRegex(), "").toFloat()*8388.608)/1000000))
+ }else if(bandwidthPerSecondInString.contains("MB", ignoreCase = true)){
+ println("After removing MB: "
+ + bandwidthPerSecondInString.replace("MB+".toRegex(), ""))
+
+ bandwidthPerSecond = String.format("%.2f", (bandwidthPerSecondInString.replace("MB+".toRegex(), "").toFloat()*8.388608))
+ }else{
+ println("After removing MB: "
+ + bandwidthPerSecondInString.replace("bytes+".toRegex(), ""))
+
+ bandwidthPerSecond = String.format("%.2f", (bandwidthPerSecondInString.replace("bytes+".toRegex(), "").toFloat()*8.388608))
+ }
+ if (count >= 30 && totalBytesReceived == 0L){
+ cancelTimer()
+ _tlsHandleZeroBytes.value = true
+ }
+ if (count > 0){
+ _updateSpeed.value = bandwidthPerSecond.toFloat()
+ _perSecondLog.value?.add(getSecondInfo(count, throughputInMBps, bandwidthPerSecond))
+ _perSecondLog.value = _perSecondLog.value
+ }
+ bytesCountPerSec = 0F
+ }
+ }
+ }
+
+ fun tcpServer(portNumber : Int) {
+ running = true
+ count = -1
+ viewModelScope.launch(Dispatchers.Main) {
+ _perSecondLog.value = mutableListOf()
+ _perSecondLog.value = _perSecondLog.value
+ isConncetedToClient.value = false
+ }
+ isExceptionOccured = false
+ mobileServerSocket.soTimeout = 30000
+ try {
+ if (mobileServerSocket.isBound){
+ println("isBound true")
+ return
+ }else{
+ mobileServerSocket.bind(InetSocketAddress(portNumber))
+ }
+ //if (!serverSocket.isBound)serverSocket.bind(InetSocketAddress(portNumber))
+ println("Server listening on port $portNumber")
+ while (running) {
+ val clientSocket = mobileServerSocket.accept()
+ handleClient(clientSocket!!)
+ }
+ } catch (e: Exception) {
+ pollTimeoutExceptionHandling(e)
+ println("Exception ${e.message}")
+ } finally {
+ //mobileServerSocket.close()
+ running = false
+ try {
+ if (mobileServerSocket != null && !mobileServerSocket.isClosed()) {
+ mobileServerSocket.close()
+ }
+ } catch (e: IOException) {
+ // Handle socket closing exceptions
+ if (isExceptionOccured){
+ viewModelScope.launch(Dispatchers.Main) {
+ _handleException.value = isExceptionOccured
+ }
+ }
+ }
+ }
+ }
+
+ fun incrementBytesReceived(bytes: Int) {
+ totalBytesReceived += bytes
+ }
+
+ private fun handleClient(clientSocket: Socket) {
+ println("Client connected: ${clientSocket.inetAddress.hostAddress}")
+ viewModelScope.launch(Dispatchers.Main) {
+ isConncetedToClient.value = true
+ }
+ startTimer()
+ val dataInputStream = DataInputStream(BufferedInputStream(clientSocket.getInputStream()))
+ val startTime = System.nanoTime()
+ try {
+ while (true) {
+ val bytesRead = dataInputStream.read(ByteArray(2460))
+ if (bytesRead == -1) break
+ incrementBytesReceived(bytesRead)
+ addBytesToCount(bytesRead)
+ }
+ } catch (e: IOException) {println("Error handling client: ${e.message}")
+ } finally {
+ cancelTimer()
+ dataInputStream.close()
+ clientSocket.close()
+ println("Client disconnected")
+ // Calculate and report throughput every second
+ coroutineScope.launch {
+ val endTime = System.nanoTime()
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ val throughputInMbps = (totalBytesReceived * 8.388608) / timeTakenInSeconds / 1_000_000
+ println("Server Throughput total time taken : $timeTakenInSeconds")
+ // Update UI or log the throughput
+ println("Server Throughput total count : $totalBytesReceived")
+ println("Server Throughput: $throughputInMbps Mbps")
+ _updateFinalPackets.value?.put("transfer", totalBytesReceived.toString())
+ _updateFinalPackets.value?.put("bandwidth", String.format("%.2f", throughputInMbps).toString())
+ viewModelScope.launch(Dispatchers.Main) {
+ _updateFinalPackets.value = _updateFinalPackets.value
+ }
+ _perSecondLog.value?.clear()
+ totalBytesReceived = 0
+ count = -1
+ }
+ }
+ }
+
+ fun stop() {
+ coroutineScope.cancel()
+ serverSocket?.close()
+ mobileServerSocket.close()
+ sslServerSocket?.close()
+ udpSocket?.close()
+ }
+
+ companion object {
+ const val DISPLAY_REFRESH_PERIOD: Long = 1000 // in milliseconds
+ }
+
+ private fun startTimer() {
+ if (timer == null) {
+ timer = Timer()
+ timerTask = PeriodicSpeedUpdate()
+ timer?.scheduleAtFixedRate(timerTask,
+ WifiThroughputViewModel.DISPLAY_REFRESH_PERIOD,
+ WifiThroughputViewModel.DISPLAY_REFRESH_PERIOD
+ )
+ }
+ }
+
+ private fun cancelTimer() {
+ bytesCountPerSec = 0F
+ timerTask?.cancel()
+ timer?.cancel()
+ timer?.purge()
+ timerTask = null
+ timer = null
+ }
+
+ fun addBytesToCount(packetSize: Int) {
+ bytesCountPerSec += packetSize
+ }
+
+ fun getSecondInfo(count : Int, throughPut: Float, bandwidth: String): String{
+ return "$count-${count+1} Sec,${bytesToHumanReadableSize(throughPut)},$bandwidth"
+ }
+
+ fun bytesToHumanReadableSize(bytes: Float) = when {
+ bytes >= 1 shl 30 -> "%.1f GB".format(bytes / (1 shl 30))
+ bytes >= 1 shl 20 -> "%.1f MB".format(bytes / (1 shl 20))
+ bytes >= 1 shl 10 -> "%.0f kB".format(bytes / (1 shl 10))
+ else -> "$bytes bytes"
+ }
+
+ fun udpClient(ipAddress : String, portNumber : Int){
+ isExceptionOccured = false
+ count = -1
+ finalThroughPut = 0
+ val BYTES_TO_SEND = 536870912.0 //317470020// Example value, set your actual byte count
+ val TEST_TIMEOUT: Long = 30000 // Timeout in milliseconds
+ val serverAddress: InetAddress
+ var socket: DatagramSocket? = null
+ var totalBytesSent = 0
+ var sentBytes: Int
+ var fail = 0
+ var pass = 0
+ val SEVER_IP = ipAddress
+ var endTime : Long = 0
+ var totalBytesTransferred = 0L
+ val buffer = ByteArray(1470)
+ var isTimerStarted = false
+ var startTime = System.nanoTime()
+
+ try {
+ serverAddress = InetAddress.getByName(SEVER_IP) // Replace with actual server address
+ socket = DatagramSocket()
+ socket.soTimeout = TEST_TIMEOUT.toInt()
+ var start = System.currentTimeMillis()
+ if(!isTimerStarted){
+ isTimerStarted = true
+ startTime = System.nanoTime()
+ start = System.currentTimeMillis()
+ startTimer()
+ }
+ val packet = DatagramPacket(
+ buffer,
+ buffer.size,
+ serverAddress,
+ portNumber
+ )
+ while (totalBytesTransferred < BYTES_TO_SEND) {
+ println("Total bytes sent so far : $totalBytesTransferred")
+ socket.send(packet)
+ val now = System.currentTimeMillis()
+
+ if ((now - start) > TEST_TIMEOUT || count >= 30) {
+ println(
+ """
+ Time Out: ${now - start}
+ """.trimIndent()
+ )
+ //socket.close()
+ break
+ }
+ sentBytes = packet.length
+ if (sentBytes < 0) {
+ println("FAIL - : $fail")
+
+ fail++
+ } else {
+ pass++
+ }
+ totalBytesTransferred += sentBytes
+
+ addBytesToCount(sentBytes)
+ if (sentBytes > 0) {
+ totalBytesSent += sentBytes
+ }
+ println("Total buffer.size : ${buffer.size}")
+
+ totalBytesTransferred += buffer.size
+ addBytesToCount(buffer.size)
+ }
+ endTime = System.nanoTime()
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ val throughputInMbps =
+ (totalBytesTransferred * 8.0) / timeTakenInSeconds / 1_000_000
+ cancelTimer()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ cancelTimer()
+ socket?.close()
+ } finally {
+ if (socket != null && !socket.isClosed) {
+ socket.close()
+ }
+
+ if(!isExceptionOccured){
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ val throughputInMbps =
+ (totalBytesTransferred * 8.0) / timeTakenInSeconds / 1_000_000
+ socket?.close()
+ cancelTimer()
+ _updateFinalPackets.value?.put("transfer", totalBytesTransferred.toString())
+ _updateFinalPackets.value?.put("bandwidth", String.format("%.2f", throughputInMbps).toString())
+ viewModelScope.launch(Dispatchers.Main) {
+ _updateFinalPackets.value = _updateFinalPackets.value
+ }
+ // _perSecondLog.value?.clear()
+ println("throughPut speed data are getting cleared to zero!!!")
+ }else{
+ viewModelScope.launch(Dispatchers.Main) {
+ _handleException.value = isExceptionOccured
+ }
+ }
+ }
+ }
+
+ fun udpServer(portNumber : Int){
+ val port = portNumber
+ var totalBytesReceived =0L
+
+ running = true
+ count = -1
+ viewModelScope.launch(Dispatchers.Main) {
+ _perSecondLog.value = mutableListOf()
+ _perSecondLog.value = _perSecondLog.value
+ }
+ // Coroutine to receive UDP packets
+ coroutineScope.launch {
+ DatagramSocket(port).use { socket ->
+ println("UDP Server listening on port $port")
+ udpSocket = socket
+ udpSocket.soTimeout = 30000
+ val buffer = ByteArray(1470)
+ var startTime = 0L
+ var firstTime = true
+ try {
+ while (true) {
+ val packet = DatagramPacket(buffer, buffer.size)
+ udpSocket.receive(packet)
+
+ if (firstTime){
+ startTime = System.nanoTime()
+ firstTime = false
+ }
+ if (packet.length > 0){
+ viewModelScope.launch(Dispatchers.Main) {
+ isConncetedToClient.value = true
+ }
+ udpSocket.soTimeout = 500
+ startTimer()
+ }
+ println("Server Throughput bytes: ${packet.length}")
+ totalBytesReceived += packet.length
+ println("totalBytesReceived : $totalBytesReceived")
+
+ incrementBytesReceived(packet.length)
+ addBytesToCount(packet.length)
+ }
+ } catch (e: Exception) {
+ cancelTimer()
+ if (count <= 0){
+ pollTimeoutExceptionHandling(e)
+ }
+ println("Error handling client: ${e.message}")
+ } finally {
+ if (!isExceptionOccured){
+ firstTime = true
+ cancelTimer()
+ println("Client disconnected")
+ // Calculate and report throughput every second
+ coroutineScope.launch {
+ val endTime = System.nanoTime()
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ val throughputInMbps = (totalBytesReceived * 8.0) / timeTakenInSeconds / 1_000_000
+ println("Server Throughput total time taken : $timeTakenInSeconds")
+ // Update UI or log the throughput
+ _updateFinalPackets.value?.put("transfer", totalBytesReceived.toString())
+ _updateFinalPackets.value?.put("bandwidth", String.format("%.2f", throughputInMbps).toString())
+ viewModelScope.launch(Dispatchers.Main) {
+ _updateFinalPackets.value = _updateFinalPackets.value
+ }
+ _perSecondLog.value?.clear()
+ totalBytesReceived = 0
+ count = -1
+ }
+ }else{
+ viewModelScope.launch(Dispatchers.Main) {
+ _handleException.value = isExceptionOccured
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fun createSSLContext(context: Context): SSLContext {
+ val keyStore = KeyStore.getInstance("PKCS12")
+ val password = "Whyyouneed!#2024".toCharArray() // Use the same password you used to create the .p12 file
+
+ val inputStream: InputStream = context.resources.openRawResource(R.raw.keystore) // Put server.p12 in res/raw
+ keyStore.load(inputStream, password)
+
+ val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
+ keyManagerFactory.init(keyStore, password)
+
+ val sslContext = SSLContext.getInstance("TLS")
+ sslContext.init(keyManagerFactory.keyManagers, null, null)
+
+ return sslContext
+ }
+
+ private var sslServerSocket: SSLServerSocket? = null
+
+ fun startTLSServer(port: Int, context: Context, isUpload: Boolean) {
+ count = -1
+ isExceptionOccured = false
+ println("Port number : $port")
+ viewModelScope.launch(Dispatchers.Main) {
+ _perSecondLog.value = mutableListOf()
+ _perSecondLog.value = _perSecondLog.value
+ isConncetedToClient.value = false
+ }
+ try {
+ val sslContext = createSSLContext(context)
+ val factory: SSLServerSocketFactory = sslContext.serverSocketFactory
+ sslServerSocket = factory.createServerSocket(port) as SSLServerSocket
+ sslServerSocket?.soTimeout = 30000
+ sslServerSocket?.let {
+ it.useTLSProtocols()
+ while (true) {
+ val socket = it.accept() // Wait for client connections
+ println("Accept done")
+ viewModelScope.launch(Dispatchers.Main) {
+ isConncetedToClient.value = true
+ }
+ // handleTLSClient(socket) // Handle client in separate thread
+ if (!isUpload){
+ handleClient(socket)
+ }else{
+ uploadData(socket!!)
+ }
+ }
+ }
+ } catch (e: Exception) {
+ pollTimeoutExceptionHandling(e)
+ e.printStackTrace()
+ }finally {
+ try {
+ if (sslServerSocket != null && !sslServerSocket!!.isClosed()) {
+ sslServerSocket!!.close()
+ }
+ } catch (e: IOException) {
+ // Handle socket closing exceptions
+ if (isExceptionOccured){
+ viewModelScope.launch(Dispatchers.Main) {
+ _handleException.value = isExceptionOccured
+ }
+ }
+ }
+ }
+ }
+
+ private fun SSLServerSocket.useTLSProtocols() {
+ // Set your required TLS protocols
+ enabledProtocols = arrayOf("TLSv1.2", "TLSv1.3") // Specify protocols as needed
+ }
+
+ fun uploadData(socket: Socket){
+ isExceptionOccured = false
+ finalThroughPut = 0
+ val TEST_TIMEOUT: Long = 30000 // Timeout in milliseconds
+ val BYTES_TO_SEND = 536870912.0 //317470020// Example value, set your actual byte count
+ val buffer = ByteArray(1370)
+
+ var outputStream : OutputStream? = null
+ var totalBytesTransferred = 0L
+ var startTime = 0L
+ var start = 0L
+ var endTime : Long = 0
+ var isTimerStarted = false
+ try{
+ outputStream = socket.getOutputStream()
+ outputStream!!.write(buffer)
+ viewModelScope.launch {
+ delay(800L)
+ }
+ while (totalBytesTransferred < BYTES_TO_SEND) {
+ if(!isTimerStarted){
+ isTimerStarted = true
+ startTime = System.nanoTime()
+ start = System.currentTimeMillis()
+ startTimer()
+ }
+ outputStream = socket.getOutputStream()
+ outputStream!!.write(buffer)
+ totalBytesTransferred += buffer.size
+ addBytesToCount(buffer.size)
+
+ val now = System.currentTimeMillis()
+ if ((now - start) > TEST_TIMEOUT || count >= 30) {
+ println(
+ """
+ Time Out: ${now - start}
+ """.trimIndent()
+ )
+ break
+ }
+ }
+ endTime = System.nanoTime()
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ println("Time taken : " + timeTakenInSeconds)
+ val throughputInMbps =
+ (totalBytesTransferred * 8.0) / timeTakenInSeconds / 1_000_000
+ println("TCP Throughput total bytes : $totalBytesTransferred")
+
+ println("TCP Throughput: $throughputInMbps Mbps")
+
+ outputStream?.close()
+ cancelTimer()
+ }catch (e: Exception){
+ endTime = System.nanoTime()
+ println("TCP Throughput: $e")
+ //isExceptionOccured = true
+ cancelTimer()
+ }finally {
+ isTimerStarted = false
+ count = -1
+ if(!isExceptionOccured){
+ val timeTakenInSeconds = TimeUnit.NANOSECONDS.toSeconds(endTime - startTime)
+ val throughputInMbps =
+ (totalBytesTransferred * 8.0) / timeTakenInSeconds / 1_000_000
+ socket.close()
+ println("TCP Throughput finally : socket connection closed")
+ cancelTimer()
+ _updateFinalPackets.value?.put("transfer", totalBytesTransferred.toString())
+ _updateFinalPackets.value?.put("bandwidth", String.format("%.2f", throughputInMbps).toString())
+ viewModelScope.launch(Dispatchers.Main) {
+ _updateFinalPackets.value = _updateFinalPackets.value
+ }
+ _perSecondLog.value?.clear()
+ }else{
+ viewModelScope.launch(Dispatchers.Main) {
+ _handleException.value = isExceptionOccured
+ }
+ }
+ }
+ }
+
+ private fun pollTimeoutExceptionHandling(e: Exception) {
+ if (e is SocketTimeoutException){
+ isExceptionOccured = true
+ }
+ }
+}
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 49ed5d65..0f24386e 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
@@ -34,6 +34,7 @@ import android.net.Uri
import android.os.*
import android.text.TextUtils
import android.util.Log
+import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
@@ -42,7 +43,6 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
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
@@ -50,8 +50,8 @@ 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.ActivityIopTestBinding
import com.siliconlabs.bledemo.databinding.DialogShareIopLogBinding
-import com.siliconlabs.bledemo.features.scan.browser.dialogs.OtaLoadingDialog
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.*
@@ -64,11 +64,11 @@ import com.siliconlabs.bledemo.features.iop_test.test_cases.ota.OtaFileManager
import com.siliconlabs.bledemo.features.iop_test.test_cases.ota.OtaFileSelectionDialog
import com.siliconlabs.bledemo.features.iop_test.test_cases.ota.OtaProgressDialog
import com.siliconlabs.bledemo.features.iop_test.utils.ErrorCodes
+import com.siliconlabs.bledemo.features.scan.browser.dialogs.OtaLoadingDialog
import com.siliconlabs.bledemo.utils.BLEUtils.setNotificationForCharacteristic
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
@@ -180,6 +180,7 @@ class IOPTestActivity : AppCompatActivity() {
private var testCaseCount = 0
private var shareMenuItem: MenuItem? = null
+ private lateinit var binding: ActivityIopTestBinding
private val mBondStateReceiver: BroadcastReceiver = object : BroadcastReceiver() {
@@ -309,7 +310,12 @@ class IOPTestActivity : AppCompatActivity() {
* Start test by item
*/
private fun startItemTest(item: Int) {
- mListener?.scrollViewToPosition(item)
+ lifecycleScope.launch {
+ withContext(Dispatchers.Main){
+ mListener?.scrollViewToPosition(item)
+ }
+ }
+
mIndexRunning = item
isTestRunning = true
@@ -829,7 +835,6 @@ class IOPTestActivity : AppCompatActivity() {
}
-
private fun startTest() {
isTestRunning = true
isTestFinished = false
@@ -845,7 +850,7 @@ class IOPTestActivity : AppCompatActivity() {
*/
private fun updateUIFooter(isRunning: Boolean) {
if (!isRunning) {
- btn_start_and_stop_test.apply {
+ binding.btnStartAndStopTest.apply {
text = getString(R.string.button_run_test)
isEnabled = true
backgroundTintList = ColorStateList.valueOf(
@@ -860,7 +865,7 @@ class IOPTestActivity : AppCompatActivity() {
mBluetoothDevice?.let { removeBond(it) }
}
} else {
- btn_start_and_stop_test?.apply {
+ binding.btnStartAndStopTest?.apply {
text = getString(R.string.button_waiting)
backgroundTintList = ColorStateList.valueOf(
ContextCompat.getColor(
@@ -873,6 +878,7 @@ class IOPTestActivity : AppCompatActivity() {
shareMenuItem?.isVisible = false
}
}
+
private fun removeBond(device: BluetoothDevice): Boolean {
return try {
return device::class.java.getMethod("removeBond").invoke(device) as Boolean
@@ -882,7 +888,6 @@ class IOPTestActivity : AppCompatActivity() {
}
-
/**
* Show information device test and progress test item
*/
@@ -890,9 +895,9 @@ class IOPTestActivity : AppCompatActivity() {
val siliconlabsTestInfo = getSiliconLabsTestInfo()
runOnUiThread {
if (isInformation || item == POSITION_TEST_CONNECTION) {
- tv_fw_name.text =
+ binding.tvFwName.text =
getString(R.string.iop_test_label_fw_name, siliconlabsTestInfo.fwName)
- tv_device_name.text =
+ binding.tvDeviceName.text =
getString(R.string.iop_test_label_device_name, siliconlabsTestInfo.phoneName)
}
val total = siliconlabsTestInfo.totalTestCase.toString()
@@ -900,7 +905,7 @@ class IOPTestActivity : AppCompatActivity() {
testCaseCount = item + mIndexStartChildrenTest + 1
}
Log.d(TAG, "The number of test case $testCaseCount")
- tv_progress.text = getString(
+ binding.tvProgress.text = getString(
R.string.iop_test_label_progress_count_test,
testCaseCount.toString(),
total
@@ -969,7 +974,8 @@ class IOPTestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_iop_test)
+ binding = ActivityIopTestBinding.inflate(LayoutInflater.from(this))
+ setContentView(binding.root)
supportActionBar?.apply {
setDisplayHomeAsUpEnabled(true)
@@ -1029,9 +1035,11 @@ class IOPTestActivity : AppCompatActivity() {
}
return true
}
+
private fun showCustomDialog() {
val dialog = Dialog(this)
- val dialogBinding: DialogShareIopLogBinding = DialogShareIopLogBinding.inflate(layoutInflater)
+ val dialogBinding: DialogShareIopLogBinding =
+ DialogShareIopLogBinding.inflate(layoutInflater)
dialog.setContentView(dialogBinding.root)
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.setCancelable(true)
@@ -1099,7 +1107,7 @@ class IOPTestActivity : AppCompatActivity() {
}
private fun handleClickEvents() {
- btn_start_and_stop_test.setOnClickListener {
+ binding.btnStartAndStopTest.setOnClickListener {
startTest()
}
}
@@ -1216,12 +1224,17 @@ class IOPTestActivity : AppCompatActivity() {
}
}
} ?: run {
- Toast.makeText(this, getString(R.string.chosen_file_not_found), Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ this,
+ getString(R.string.chosen_file_not_found),
+ Toast.LENGTH_SHORT
+ ).show()
}
}
}
}
}
+
/**
* Save log data into File
*/
@@ -1230,10 +1243,10 @@ class IOPTestActivity : AppCompatActivity() {
val outputStream = contentResolver.openOutputStream(uri)
outputStream?.use { fOut ->
OutputStreamWriter(fOut).use { myOutWriter ->
- if (isLogcatData){
+ if (isLogcatData) {
myOutWriter.write(logs + "\n" + getDataLog())
- }else{
- myOutWriter.write( getDataLog())
+ } else {
+ myOutWriter.write(getDataLog())
}
@@ -1689,7 +1702,7 @@ class IOPTestActivity : AppCompatActivity() {
val pathFile = getSiliconLabsTestInfo().phoneName
pathFile.replace(" ", "")
if (isLogcatData) {
- return "logcat"+"_" + getDate("EEE MMM dd HH_mm_ss z yyyy") + ".txt"
+ return "logcat" + "_" + getDate("EEE MMM dd HH_mm_ss z yyyy") + ".txt"
} else {
return pathFile + "_" + boardName + "_" + getDate("yyyy_MM_dd_HH_mm_ss") + ".txt"
@@ -1697,8 +1710,6 @@ class IOPTestActivity : AppCompatActivity() {
}
-
-
/**
* Get Date currently
*/
@@ -1712,14 +1723,15 @@ class IOPTestActivity : AppCompatActivity() {
private fun getDataLog(): String {
return getSiliconLabsTestInfo().toString()
}
+
private fun shareLogDataTestByEmail(uri: Uri) {
try {
val message = "Please check the attachment to get the log file."
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
- if (isLogcatData){
+ if (isLogcatData) {
putExtra(Intent.EXTRA_SUBJECT, "[Silabs] Application Debug log")
- }else{
+ } else {
putExtra(Intent.EXTRA_SUBJECT, "[Silabs] Test log")
}
@@ -1735,7 +1747,6 @@ class IOPTestActivity : AppCompatActivity() {
}
-
/**
* Perform the test by item test case
*/
@@ -2080,7 +2091,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")
+ Log.d(TAG, "CASE 3: iopPhase3RunTestCaseBonding" + "Write value 0x00 to CCCD")
CCCD_value[0] = 1
iopPhase3ExtraDescriptor?.setValue(CCCD_value)
mBluetoothGatt?.writeDescriptor(iopPhase3ExtraDescriptor)
@@ -2091,17 +2102,20 @@ class IOPTestActivity : AppCompatActivity() {
// disconnect
4 -> {
- Log.d(TAG,"CASE 4: iopPhase3RunTestCaseBonding"+ "disconnect")
+ Log.d(TAG, "CASE 4: iopPhase3RunTestCaseBonding" + "disconnect")
disconnectGatt(mBluetoothGatt)
- }
+ }
6 -> {
mBluetoothGatt?.readDescriptor(iopPhase3ExtraDescriptor)
- Log.d(TAG,"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
+ isCCCDPass = true
} else {
isCCCDPass = false
updateDataTestFailed(POSITION_TEST_IOP3_SECURITY)
@@ -2115,7 +2129,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(TAG,"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)
@@ -2124,7 +2138,10 @@ class IOPTestActivity : AppCompatActivity() {
8 -> {
mBluetoothGatt?.readDescriptor(iopPhase3ExtraDescriptor)
read_CCCD_value = iopPhase3ExtraDescriptor?.getValue()!!.copyOf()
- Log.d(TAG,"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
@@ -2395,8 +2412,6 @@ 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/adapters/IOPTestViewHolder.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/adapters/IOPTestViewHolder.kt
index bb7381b8..5d6904e7 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/adapters/IOPTestViewHolder.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/adapters/IOPTestViewHolder.kt
@@ -5,15 +5,16 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.AdapterIopTestBinding
import com.siliconlabs.bledemo.features.iop_test.models.ItemTestCaseInfo
-import kotlinx.android.synthetic.main.adapter_iop_test.view.*
-class IOPTestViewHolder(view: View) : RecyclerView.ViewHolder(view) {
- private val ivTestStatus = view.iv_test_status
- private val tvTestTitle = view.tv_test_title
- private val tvTestDescription = view.tv_test_description
- private val tvTestStatus = view.tv_test_status
- private val pbTestProgress = view.pb_test_progress
+
+class IOPTestViewHolder(view: AdapterIopTestBinding) : RecyclerView.ViewHolder(view.root) {
+ private val ivTestStatus = view.ivTestStatus
+ private val tvTestTitle = view.tvTestTitle
+ private val tvTestDescription = view.tvTestDescription
+ private val tvTestStatus = view.tvTestStatus
+ private val pbTestProgress = view.pbTestProgress
fun bind(info: ItemTestCaseInfo) {
tvTestTitle.text = info.titlesTest
@@ -32,6 +33,7 @@ class IOPTestViewHolder(view: View) : RecyclerView.ViewHolder(view) {
tvTestStatus.setTextColor(context.getColor(R.color.silabs_red))
pbTestProgress.visibility = View.GONE
}
+
1 -> {
ivTestStatus.setBackgroundResource(R.drawable.ic_test_pass)
ivTestStatus.visibility = View.VISIBLE
@@ -39,12 +41,14 @@ class IOPTestViewHolder(view: View) : RecyclerView.ViewHolder(view) {
tvTestStatus.setTextColor(context.getColor(R.color.silabs_blue))
pbTestProgress.visibility = View.GONE
}
+
2 -> {
ivTestStatus.visibility = View.GONE
tvTestStatus.visibility = View.GONE
pbTestProgress.visibility = View.VISIBLE
}
+
else -> {
ivTestStatus.visibility = View.GONE
tvTestStatus.visibility = View.VISIBLE
@@ -57,7 +61,8 @@ class IOPTestViewHolder(view: View) : RecyclerView.ViewHolder(view) {
companion object {
fun create(parent: ViewGroup): IOPTestViewHolder {
- val view = LayoutInflater.from(parent.context).inflate(R.layout.adapter_iop_test, parent, false)
+ val view =
+ AdapterIopTestBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return IOPTestViewHolder(view)
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/dialogs/AboutIopDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/dialogs/AboutIopDialog.kt
index b83aa675..fd3ac3d1 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/dialogs/AboutIopDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/dialogs/AboutIopDialog.kt
@@ -8,15 +8,22 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_info_iop.*
+import com.siliconlabs.bledemo.databinding.DialogInfoIopBinding
+
class AboutIopDialog : BaseDialogFragment(
- hasCustomWidth = true,
- isCanceledOnTouchOutside = true
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = true
) {
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_info_iop, container, false)
+ private lateinit var binding: DialogInfoIopBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogInfoIopBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -25,9 +32,9 @@ class AboutIopDialog : BaseDialogFragment(
}
private fun handleClickEvents() {
- btn_ok.setOnClickListener { dismiss() }
+ binding.btnOk.setOnClickListener { dismiss() }
- btn_interoperability_test.setOnClickListener {
+ binding.btnInteroperabilityTest.setOnClickListener {
handleClickOnInteroperabilityTest()
}
}
@@ -40,6 +47,7 @@ class AboutIopDialog : BaseDialogFragment(
}
companion object {
- private const val IOP_LINK = "https://www.silabs.com/documents/public/application-notes/an1346-running-ble-iop-test.pdf"
+ private const val IOP_LINK =
+ "https://www.silabs.com/documents/public/application-notes/an1346-running-ble-iop-test.pdf"
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/fragments/IOPTestFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/fragments/IOPTestFragment.kt
index 8aa49488..ae9e194c 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/fragments/IOPTestFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/fragments/IOPTestFragment.kt
@@ -20,18 +20,20 @@ import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
+import by.kirich1409.viewbindingdelegate.viewBinding
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.features.iop_test.activities.IOPTestActivity
import com.siliconlabs.bledemo.features.iop_test.adapters.IOPTestAdapter
import com.siliconlabs.bledemo.features.iop_test.models.IOPTest
import com.siliconlabs.bledemo.features.iop_test.models.ItemTestCaseInfo
import com.siliconlabs.bledemo.common.other.CardViewListDecoration
-import kotlinx.android.synthetic.main.fragment_iop_test.*
+import com.siliconlabs.bledemo.databinding.FragmentIopTestBinding
import java.util.*
class IOPTestFragment : Fragment(R.layout.fragment_iop_test), IOPTestActivity.Listener {
private lateinit var testAdapter: IOPTestAdapter
private var listItemTest: List = ArrayList()
+ private val binding by viewBinding(FragmentIopTestBinding::bind)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -46,7 +48,8 @@ class IOPTestFragment : Fragment(R.layout.fragment_iop_test), IOPTestActivity.Li
private fun initAdapter() {
testAdapter = IOPTestAdapter(listItemTest)
- rv_iop_tests.apply {
+
+ binding.rvIopTests.apply {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
addItemDecoration(CardViewListDecoration())
this.adapter = testAdapter
@@ -54,8 +57,8 @@ class IOPTestFragment : Fragment(R.layout.fragment_iop_test), IOPTestActivity.Li
}
override fun scrollViewToPosition(position: Int) {
- rv_iop_tests.post {
- rv_iop_tests.smoothScrollToPosition(position)
+ binding.rvIopTests.post {
+ binding.rvIopTests.smoothScrollToPosition(position)
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/utils/DialogDeviceInfoFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/utils/DialogDeviceInfoFragment.kt
index ae5f1883..8742b29b 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/utils/DialogDeviceInfoFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/utils/DialogDeviceInfoFragment.kt
@@ -3,6 +3,8 @@ package com.siliconlabs.bledemo.features.iop_test.utils
import android.app.AlertDialog
import android.app.Dialog
import android.content.DialogInterface
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -28,6 +30,10 @@ class DialogDeviceInfoFragment : DialogFragment() {
savedInstanceState: Bundle?
): View? {
binding = DialogDeviceInfoLayoutBinding.inflate(inflater, container, false)
+ if (dialog != null && dialog!!.window != null) {
+ dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ dialog!!.setCanceledOnTouchOutside(false)
+ }
return binding.root
}
@@ -56,30 +62,6 @@ class DialogDeviceInfoFragment : DialogFragment() {
binding.btnNegative.text = negativeButtonText
}
- /*override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- val builder = AlertDialog.Builder(requireActivity())
-
- builder.setTitle(title)
- builder.setMessage(message)
-
- if (positiveButtonText != null) {
- builder.setPositiveButton(positiveButtonText, positiveClickListener)
- }
-
- if (negativeButtonText != null) {
- builder.setNegativeButton(negativeButtonText, negativeClickListener)
- }
-
- val dialog = builder.create()
- dialog.setOnShowListener {
- dialogShowing = true
- }
- dialog.setOnDismissListener {
- dialogShowing = false
- }
-
- return dialog
- }*/
// Builder pattern for setting dialog properties
class Builder {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/utils/Utils.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/utils/Utils.kt
index feca3c23..9e2c8af0 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/utils/Utils.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/utils/Utils.kt
@@ -40,4 +40,5 @@ class Utils {
return (capitalize(manufacturer) + "_" + model).replace(" ", "_")
}
}
+
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/active_connections/fragments/ConnectionsFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/active_connections/fragments/ConnectionsFragment.kt
index 30378b51..5bccef1d 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/active_connections/fragments/ConnectionsFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/active_connections/fragments/ConnectionsFragment.kt
@@ -22,6 +22,7 @@ import com.siliconlabs.bledemo.common.other.CardViewListDecoration
import com.siliconlabs.bledemo.home_screen.base.ViewPagerFragment
import com.siliconlabs.bledemo.home_screen.base.BaseServiceDependentMainMenuFragment
import com.siliconlabs.bledemo.home_screen.base.BluetoothDependent
+import com.siliconlabs.bledemo.home_screen.base.NotificationDependent
class ConnectionsFragment : BaseServiceDependentMainMenuFragment() {
@@ -33,7 +34,9 @@ class ConnectionsFragment : BaseServiceDependentMainMenuFragment() {
override fun onAttach(context: Context) {
super.onAttach(context)
- service = (activity as MainActivity).bluetoothService!!
+ if(null != (activity as MainActivity).bluetoothService){
+ service = (activity as MainActivity).bluetoothService!!
+ }
viewModel = (parentFragment as ViewPagerFragment).getScanFragment().viewModel
}
@@ -69,6 +72,7 @@ class ConnectionsFragment : BaseServiceDependentMainMenuFragment() {
}
}
+
override fun onResume() {
super.onResume()
service.registerGattCallback(gattCallback)
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/activities/DeviceServicesActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/activities/DeviceServicesActivity.kt
index 48833148..9421acf4 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/activities/DeviceServicesActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/activities/DeviceServicesActivity.kt
@@ -35,6 +35,7 @@ import android.widget.*
import androidx.core.content.ContextCompat.startActivity
import androidx.core.view.children
import androidx.fragment.app.Fragment
+import by.kirich1409.viewbindingdelegate.viewBinding
import com.siliconlabs.bledemo.base.activities.BaseActivity
import com.siliconlabs.bledemo.bluetooth.ble.ErrorCodes
import com.siliconlabs.bledemo.bluetooth.ble.TimeoutGattCallback
@@ -45,8 +46,8 @@ import com.siliconlabs.bledemo.features.scan.browser.fragments.*
import com.siliconlabs.bledemo.features.scan.browser.models.OtaFileType
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.common.views.FlyInBar
+import com.siliconlabs.bledemo.databinding.ActivityDeviceServicesBinding
import com.siliconlabs.bledemo.utils.*
-import kotlinx.android.synthetic.main.activity_device_services.*
import timber.log.Timber
import java.io.*
import java.util.*
@@ -100,13 +101,16 @@ class DeviceServicesActivity : BaseActivity() {
private var retryAttempts = 0
- private val hideFabOnScrollChangeListener = OnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
- if (scrollY > oldScrollY) {
- btn_bond_action.hide()
- } else {
- btn_bond_action.show()
+ private lateinit var binding:ActivityDeviceServicesBinding
+
+ private val hideFabOnScrollChangeListener =
+ OnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
+ if (scrollY > oldScrollY) {
+ binding.btnBondAction.hide()
+ } else {
+ binding.btnBondAction.show()
+ }
}
- }
private val remoteServicesFragment = RemoteServicesFragment(hideFabOnScrollChangeListener)
private val localServicesFragment = LocalServicesFragment()
@@ -115,7 +119,8 @@ class DeviceServicesActivity : BaseActivity() {
private val bondStateChangeListener = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == BluetoothDevice.ACTION_BOND_STATE_CHANGED) {
- val newState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)
+ val newState =
+ intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)
displayBondState(newState)
if (newState == BluetoothDevice.BOND_BONDED) {
showMessage(getString(R.string.device_bonded_successfully))
@@ -140,7 +145,7 @@ class DeviceServicesActivity : BaseActivity() {
override fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int, status: Int) {
if (viewState == ViewState.IDLE) {
super.onReadRemoteRssi(gatt, rssi, status)
- runOnUiThread { tv_rssi.text = resources.getString(R.string.n_dBm, rssi) }
+ runOnUiThread { binding.tvRssi.text = resources.getString(R.string.n_dBm, rssi) }
}
}
@@ -150,15 +155,17 @@ class DeviceServicesActivity : BaseActivity() {
when (mtuReadType) {
MtuReadType.VIEW_INITIALIZATION -> {
MTU = if (status == BluetoothGatt.GATT_SUCCESS) mtu
- else DEFAULT_MTU_VALUE
+ else DEFAULT_MTU_VALUE
gatt.requestConnectionPriority(connectionPriority)
}
+
MtuReadType.UPLOAD_INITIALIZATION -> {
MTU = if (status == BluetoothGatt.GATT_SUCCESS) mtu
- else DEFAULT_MTU_VALUE
+ else DEFAULT_MTU_VALUE
gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH) // optimize upload speed
writeOtaControl(OTA_CONTROL_START_COMMAND)
}
+
MtuReadType.USER_REQUESTED -> {
if (status == BluetoothGatt.GATT_SUCCESS) {
MTU = mtu
@@ -183,33 +190,47 @@ class DeviceServicesActivity : BaseActivity() {
when (newState) {
BluetoothGatt.STATE_CONNECTED -> {
if (viewState == ViewState.REBOOTING ||
- viewState == ViewState.REBOOTING_NEW_FIRMWARE) {
+ viewState == ViewState.REBOOTING_NEW_FIRMWARE
+ ) {
handler.postDelayed({
bluetoothGatt = null
gatt.discoverServices()
}, 250)
}
}
+
BluetoothGatt.STATE_DISCONNECTED -> {
when (viewState) {
ViewState.IDLE -> when (status) {
0 -> finish()
else -> {
- showLongMessage(ErrorCodes.getDeviceDisconnectedMessage(getDeviceName(), status))
+ showLongMessage(
+ ErrorCodes.getDeviceDisconnectedMessage(
+ getDeviceName(),
+ status
+ )
+ )
finish()
}
}
+
ViewState.REBOOTING -> when (status) {
19 -> {
/* Device is reconnecting into ota mode */
showInitializationInfo()
}
+
0 -> {} /* Device reconnecting for another file upload, let it be */
else -> showErrorDialog(status)
}
+
ViewState.UPLOADING -> showErrorDialog(status)
- ViewState.REBOOTING_NEW_FIRMWARE -> { /* Do nothing */ }
- else -> { finish() }
+ ViewState.REBOOTING_NEW_FIRMWARE -> { /* Do nothing */
+ }
+
+ else -> {
+ finish()
+ }
}
}
}
@@ -249,31 +270,34 @@ class DeviceServicesActivity : BaseActivity() {
if (status != BluetoothGatt.GATT_SUCCESS) {
showErrorDialog(status)
if (viewState == ViewState.UPLOADING) viewState = ViewState.IDLE
- }
- else {
+ } else {
when (characteristic.uuid) {
- UuidConsts.OTA_CONTROL -> { when (characteristic.value[0]) {
- 0x00.toByte() -> {
- if (viewState == ViewState.REBOOTING) {
- reloadDeviceIntoOtaMode()
- }
- else if (viewState == ViewState.INITIALIZING_UPLOAD) {
- viewState = ViewState.UPLOADING
- startOtaUpload()
+ UuidConsts.OTA_CONTROL -> {
+ when (characteristic.value[0]) {
+ 0x00.toByte() -> {
+ if (viewState == ViewState.REBOOTING) {
+ reloadDeviceIntoOtaMode()
+ } else if (viewState == ViewState.INITIALIZING_UPLOAD) {
+ viewState = ViewState.UPLOADING
+ startOtaUpload()
+ }
}
- }
- 0x03.toByte() -> {
- if (viewState == ViewState.UPLOADING) {
- viewState = ViewState.IDLE
- if (boolFullOTA) {
- prepareForNextUpload()
- } else {
- runOnUiThread { otaProgressDialog?.toggleEndButton(isEnabled = true) }
+
+ 0x03.toByte() -> {
+ if (viewState == ViewState.UPLOADING) {
+ viewState = ViewState.IDLE
+ if (boolFullOTA) {
+ prepareForNextUpload()
+ } else {
+ runOnUiThread { otaProgressDialog?.toggleEndButton(isEnabled = true) }
+ }
}
}
+
+ else -> {}
}
- else -> { }
- } }
+ }
+
UuidConsts.OTA_DATA -> handleReliableUploadResponse()
}
}
@@ -281,19 +305,30 @@ class DeviceServicesActivity : BaseActivity() {
}
//CALLBACK ON DESCRIPTOR WRITE
- override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt,
+ descriptor: BluetoothGattDescriptor,
+ status: Int
+ ) {
super.onDescriptorWrite(gatt, descriptor, status)
remoteServicesFragment.updateDescriptorView(descriptor)
}
//CALLBACK ON DESCRIPTOR READ
- override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt,
+ descriptor: BluetoothGattDescriptor,
+ status: Int
+ ) {
super.onDescriptorRead(gatt, descriptor, status)
remoteServicesFragment.updateDescriptorView(descriptor)
}
//CALLBACK ON CHARACTERISTIC CHANGED VALUE (READ - CHARACTERISTIC NOTIFICATION)
- override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic
+ ) {
super.onCharacteristicChanged(gatt, characteristic)
remoteServicesFragment.updateCharacteristicView(characteristic)
}
@@ -306,7 +341,8 @@ class DeviceServicesActivity : BaseActivity() {
if (status != BluetoothGatt.GATT_SUCCESS) showErrorDialog(status)
else {
printServicesInfo(gatt)
- otaDataCharPresent = (gatt.getService(UuidConsts.OTA_SERVICE)?.getCharacteristic(UuidConsts.OTA_DATA) != null)
+ otaDataCharPresent = (gatt.getService(UuidConsts.OTA_SERVICE)
+ ?.getCharacteristic(UuidConsts.OTA_DATA) != null)
when (viewState) {
ViewState.REFRESHING_SERVICES -> {
@@ -315,6 +351,7 @@ class DeviceServicesActivity : BaseActivity() {
}, GATT_FETCH_ON_SERVICE_DISCOVERED_DELAY)
viewState = ViewState.IDLE
}
+
ViewState.IDLE -> {
handler.postDelayed({
initServicesFragments(bluetoothGatt?.services.orEmpty())
@@ -322,16 +359,18 @@ class DeviceServicesActivity : BaseActivity() {
gatt.requestMtu(INITIALIZATION_MTU_VALUE)
}, GATT_FETCH_ON_SERVICE_DISCOVERED_DELAY)
}
+
ViewState.REBOOTING -> {
viewState = ViewState.INITIALIZING_UPLOAD
mtuReadType = MtuReadType.UPLOAD_INITIALIZATION
bluetoothGatt?.requestMtu(INITIALIZATION_MTU_VALUE)
}
+
ViewState.REBOOTING_NEW_FIRMWARE -> {
bluetoothGatt?.readCharacteristic(getDeviceNameCharacteristic())
}
- else -> { }
+ else -> {}
}
}
}
@@ -348,16 +387,20 @@ class DeviceServicesActivity : BaseActivity() {
hideOtaLoadingDialog()
otafile = readChosenFile()
pack = 0
- if (reliable) { setupMtuDivisible() }
+ if (reliable) {
+ setupMtuDivisible()
+ }
hideOtaProgressDialog()
- showOtaProgressDialog(OtaProgressDialog.OtaInfo(
+ showOtaProgressDialog(
+ OtaProgressDialog.OtaInfo(
prepareFilename(),
otafile?.size,
if (reliable) mtuDivisible else MTU,
doubleStepUpload,
if (doubleStepUpload) stackPath != "" else true
- ))
+ )
+ )
Thread {
Thread.sleep(DIALOG_DELAY)
@@ -423,7 +466,8 @@ class DeviceServicesActivity : BaseActivity() {
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_device_services)
+ binding = ActivityDeviceServicesBinding.inflate(LayoutInflater.from(this))
+ setContentView(binding.root)
bluetoothDevice = intent.getParcelableExtra(CONNECTED_DEVICE)
@@ -444,18 +488,21 @@ class DeviceServicesActivity : BaseActivity() {
add(R.id.services_fragment_container, remoteServicesFragment)
}.commit()
- services_bottom_nav.setOnNavigationItemSelectedListener { item ->
+
+ binding.servicesBottomNav.setOnNavigationItemSelectedListener { item ->
(when (item.itemId) {
R.id.services_nav_remote -> {
toggleRemoteActions(isRemoteFragmentOn = true)
supportActionBar?.title = getDeviceName()
remoteServicesFragment
}
+
R.id.services_nav_local -> {
toggleRemoteActions(isRemoteFragmentOn = false)
supportActionBar?.title = bluetoothService?.bluetoothAdapter?.name
localServicesFragment
}
+
else -> null
})?.let { newFragment ->
supportFragmentManager.beginTransaction().apply {
@@ -469,12 +516,13 @@ class DeviceServicesActivity : BaseActivity() {
}
private fun toggleRemoteActions(isRemoteFragmentOn: Boolean) {
- btn_bond_action.visibility =
- if (isRemoteFragmentOn) View.VISIBLE
- else View.GONE
- connection_info.visibility =
- if (isRemoteFragmentOn) View.VISIBLE
- else View.GONE
+ binding.btnBondAction.visibility =
+ if (isRemoteFragmentOn) View.VISIBLE
+ else View.GONE
+
+ binding.connectionInfo.visibility =
+ if (isRemoteFragmentOn) View.VISIBLE
+ else View.GONE
toggleMenuItemsVisibility(isRemoteFragmentOn)
}
@@ -493,27 +541,35 @@ class DeviceServicesActivity : BaseActivity() {
}
private fun setupUiListeners() {
- tv_ota_firmware.setOnClickListener {
+ binding.tvOtaFirmware.setOnClickListener {
if (isUiCreated) checkForOtaCharacteristic()
}
- btn_bond_action.setOnClickListener {
- bluetoothGatt?.device?.let { when (it.bondState) {
- BluetoothDevice.BOND_BONDED -> askUnbondDevice(it)
- BluetoothDevice.BOND_NONE -> it.createBond()
- else -> { }
- } }
+ binding.btnBondAction.setOnClickListener {
+ bluetoothGatt?.device?.let {
+ when (it.bondState) {
+ BluetoothDevice.BOND_BONDED -> askUnbondDevice(it)
+ BluetoothDevice.BOND_NONE -> it.createBond()
+ else -> {}
+ }
+ }
}
}
private fun checkForOtaCharacteristic() {
if (getOtaControlCharacteristic() != null) showOtaConfigDialog()
- else OtaCharacteristicMissingDialog().show(supportFragmentManager, "ota_characteristic_missing_dialog")
+ else OtaCharacteristicMissingDialog().show(
+ supportFragmentManager,
+ "ota_characteristic_missing_dialog"
+ )
}
private fun registerReceivers() {
registerReceiver(bluetoothReceiver, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
- registerReceiver(bondStateChangeListener, IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED))
+ registerReceiver(
+ bondStateChangeListener,
+ IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
+ )
}
@@ -522,47 +578,54 @@ class DeviceServicesActivity : BaseActivity() {
when (state) {
BluetoothDevice.BOND_BONDED -> {
- tv_bond_state.text = getString(R.string.bonded)
- btn_bond_action.apply {
+
+ binding.tvBondState.text = getString(R.string.bonded)
+ binding.btnBondAction.apply {
isEnabled = true
text = getString(R.string.delete_bond)
setIsActionOn(true)
}
}
+
BluetoothDevice.BOND_BONDING -> {
- tv_bond_state.text = getString(R.string.bonding)
- btn_bond_action.apply {
+ binding.tvBondState.text = getString(R.string.bonding)
+ binding.btnBondAction.apply {
isEnabled = false
text = getString(R.string.bonding)
}
}
+
BluetoothDevice.BOND_NONE -> {
- tv_bond_state.text = getString(R.string.not_bonded)
- btn_bond_action.apply {
+ binding.tvBondState.text = getString(R.string.not_bonded)
+ binding.btnBondAction.apply {
isEnabled = true
text = getString(R.string.create_bond)
setIsActionOn(false)
}
}
- else -> { }
+
+ else -> {}
}
}
- private fun getOtaControlCharacteristic() : BluetoothGattCharacteristic? {
- return bluetoothGatt?.getService(UuidConsts.OTA_SERVICE)?.getCharacteristic(UuidConsts.OTA_CONTROL)
+ private fun getOtaControlCharacteristic(): BluetoothGattCharacteristic? {
+ return bluetoothGatt?.getService(UuidConsts.OTA_SERVICE)
+ ?.getCharacteristic(UuidConsts.OTA_CONTROL)
}
- private fun getDeviceNameCharacteristic() : BluetoothGattCharacteristic? {
- return bluetoothGatt?.getService(UuidConsts.GENERIC_ACCESS)?.getCharacteristic(UuidConsts.DEVICE_NAME)
+ private fun getDeviceNameCharacteristic(): BluetoothGattCharacteristic? {
+ return bluetoothGatt?.getService(UuidConsts.GENERIC_ACCESS)
+ ?.getCharacteristic(UuidConsts.DEVICE_NAME)
}
private fun setActivityResult() {
setResult(REFRESH_INFO_RESULT_CODE, Intent().apply {
putExtra(CONNECTED_DEVICE, bluetoothDevice)
- putExtra(CONNECTION_STATE,
- if (bluetoothService?.isGattConnected(bluetoothDevice?.address) == true) BluetoothGatt.STATE_CONNECTED
- else BluetoothGatt.STATE_DISCONNECTED
+ putExtra(
+ CONNECTION_STATE,
+ if (bluetoothService?.isGattConnected(bluetoothDevice?.address) == true) BluetoothGatt.STATE_CONNECTED
+ else BluetoothGatt.STATE_DISCONNECTED
)
})
}
@@ -620,18 +683,21 @@ class DeviceServicesActivity : BaseActivity() {
R.id.show_logs -> showLogFragment()
R.id.request_priority -> {
ConnectionRequestDialog(connectionPriority, connectionRequestCallback)
- .show(supportFragmentManager, CONNECTION_REQUEST_DIALOG_FRAGMENT)
+ .show(supportFragmentManager, CONNECTION_REQUEST_DIALOG_FRAGMENT)
}
+
R.id.request_mtu -> {
mtuRequestDialog = MtuRequestDialog(MTU, mtuRequestCallback).also {
it.show(supportFragmentManager, MTU_REQUEST_DIALOG_FRAGMENT)
}
}
+
android.R.id.home -> {
onBackPressed()
return true
}
- else -> { }
+
+ else -> {}
}
return super.onOptionsItemSelected(item)
}
@@ -640,8 +706,9 @@ class DeviceServicesActivity : BaseActivity() {
super.onBackPressed()
if (isLogFragmentOn) {
- fragment_container.visibility = View.GONE
- services_container.visibility = View.VISIBLE
+
+ binding.fragmentContainer.visibility = View.GONE
+ binding.servicesContainer.visibility = View.VISIBLE
isLogFragmentOn = false
supportActionBar?.title = bluetoothDevice?.name
toggleMenuItemsVisibility(areVisible = true)
@@ -652,12 +719,16 @@ class DeviceServicesActivity : BaseActivity() {
override fun onConnectionPriorityRequested(priority: Int) {
bluetoothGatt?.requestConnectionPriority(priority)
connectionPriority = priority
- showMessage(getString(when (priority) {
- BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER -> R.string.connection_priority_low
- BluetoothGatt.CONNECTION_PRIORITY_BALANCED -> R.string.connection_priority_balanced
- BluetoothGatt.CONNECTION_PRIORITY_HIGH -> R.string.connection_priority_high
- else -> R.string.connection_priority_low
- }))
+ showMessage(
+ getString(
+ when (priority) {
+ BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER -> R.string.connection_priority_low
+ BluetoothGatt.CONNECTION_PRIORITY_BALANCED -> R.string.connection_priority_balanced
+ BluetoothGatt.CONNECTION_PRIORITY_HIGH -> R.string.connection_priority_high
+ else -> R.string.connection_priority_low
+ }
+ )
+ )
}
}
@@ -674,8 +745,9 @@ class DeviceServicesActivity : BaseActivity() {
addToBackStack(null)
}.commit()
- fragment_container.visibility = View.VISIBLE
- services_container.visibility = View.GONE
+ binding.fragmentContainer.visibility = View.VISIBLE
+ binding.servicesContainer
+ binding.servicesContainer.visibility = View.GONE
toggleMenuItemsVisibility(areVisible = false)
isLogFragmentOn = true
}
@@ -784,8 +856,14 @@ class DeviceServicesActivity : BaseActivity() {
private fun sendFileChooserIntent() {
Intent(Intent.ACTION_GET_CONTENT)
.apply { type = "*/*" }
- .also { startActivityForResult(Intent.createChooser(it,
- getString(R.string.ota_choose_file)), FILE_CHOOSER_REQUEST_CODE) }
+ .also {
+ startActivityForResult(
+ Intent.createChooser(
+ it,
+ getString(R.string.ota_choose_file)
+ ), FILE_CHOOSER_REQUEST_CODE
+ )
+ }
}
private fun hideOtaProgressDialog() {
@@ -890,23 +968,43 @@ class DeviceServicesActivity : BaseActivity() {
j++
if (j >= MTU - 3 || i >= (datathread.size - 1)) {
var wait = System.nanoTime()
- val charac = bluetoothGatt?.getService(UuidConsts.OTA_SERVICE)?.getCharacteristic(
- UuidConsts.OTA_DATA
- )
+ val charac =
+ bluetoothGatt?.getService(UuidConsts.OTA_SERVICE)?.getCharacteristic(
+ UuidConsts.OTA_DATA
+ )
charac?.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
val progress = ((i + 1).toFloat() / datathread.size) * 100
- val bitrate = (((i + 1) * (8.0)).toFloat() / (((wait - start) / 1000000.0).toFloat()))
+ val bitrate =
+ (((i + 1) * (8.0)).toFloat() / (((wait - start) / 1000000.0).toFloat()))
if (j < MTU - 3) {
val end = ByteArray(j)
System.arraycopy(value, 0, end, 0, j)
- Log.d("Progress", "sent " + (i + 1) + " / " + datathread.size + " - " + String.format("%.1f", progress) + " % - " + String.format("%.2fkbit/s", bitrate) + " - " + Converters.bytesToHexWhitespaceDelimited(end))
+ Log.d(
+ "Progress",
+ "sent " + (i + 1) + " / " + datathread.size + " - " + String.format(
+ "%.1f",
+ progress
+ ) + " % - " + String.format(
+ "%.2fkbit/s",
+ bitrate
+ ) + " - " + Converters.bytesToHexWhitespaceDelimited(end)
+ )
runOnUiThread {
otaProgressDialog?.updateDataProgress(progress.toInt())
}
charac?.value = end
} else {
j = 0
- Log.d("Progress", "sent " + (i + 1) + " / " + datathread.size + " - " + String.format("%.1f", progress) + " % - " + String.format("%.2fkbit/s", bitrate) + " - " + Converters.bytesToHexWhitespaceDelimited(value))
+ Log.d(
+ "Progress",
+ "sent " + (i + 1) + " / " + datathread.size + " - " + String.format(
+ "%.1f",
+ progress
+ ) + " % - " + String.format(
+ "%.2fkbit/s",
+ bitrate
+ ) + " - " + Converters.bytesToHexWhitespaceDelimited(value)
+ )
runOnUiThread {
otaProgressDialog?.updateDataProgress(progress.toInt())
}
@@ -960,7 +1058,12 @@ class DeviceServicesActivity : BaseActivity() {
} else writearray[j] = otafile!![i]
}
pgss = ((pack + last).toFloat() / (otafile?.size!! - 1)) * 100
- Log.d("characte", "last: " + pack + " / " + (pack + last) + " : " + Converters.bytesToHexWhitespaceDelimited(writearray))
+ Log.d(
+ "characte",
+ "last: " + pack + " / " + (pack + last) + " : " + Converters.bytesToHexWhitespaceDelimited(
+ writearray
+ )
+ )
} else {
var j = 0
writearray = ByteArray(mtuDivisible)
@@ -969,9 +1072,15 @@ class DeviceServicesActivity : BaseActivity() {
j++
}
pgss = ((pack + mtuDivisible).toFloat() / (otafile?.size!! - 1)) * 100
- Log.d("characte", "pack: " + pack + " / " + (pack + mtuDivisible) + " : " + Converters.bytesToHexWhitespaceDelimited(writearray))
+ Log.d(
+ "characte",
+ "pack: " + pack + " / " + (pack + mtuDivisible) + " : " + Converters.bytesToHexWhitespaceDelimited(
+ writearray
+ )
+ )
}
- val charac = bluetoothGatt?.getService(UuidConsts.OTA_SERVICE)?.getCharacteristic(UuidConsts.OTA_DATA)
+ val charac = bluetoothGatt?.getService(UuidConsts.OTA_SERVICE)
+ ?.getCharacteristic(UuidConsts.OTA_DATA)
charac?.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
charac?.value = writearray
bluetoothGatt?.writeCharacteristic(charac)
@@ -979,17 +1088,19 @@ class DeviceServicesActivity : BaseActivity() {
val bitrate = 8 * pack.toFloat() / waiting_time
if (pack > 0) {
handler.post {
- runOnUiThread { otaProgressDialog?.let {
+ runOnUiThread {
+ otaProgressDialog?.let {
it.updateDataRate(bitrate)
it.updateDataProgress(pgss.toInt())
- } }
+ }
+ }
}
} else {
otatime = System.currentTimeMillis()
}
}
- private fun readChosenFile() : ByteArray? {
+ private fun readChosenFile(): ByteArray? {
return try {
val file: File
if (stackPath != "" && doubleStepUpload) {
@@ -1011,7 +1122,7 @@ class DeviceServicesActivity : BaseActivity() {
}
}
- private fun prepareFilename() : String {
+ private fun prepareFilename(): String {
return if (stackPath != "" && doubleStepUpload) {
val last = stackPath.lastIndexOf(File.separator)
getString(R.string.ota_filename_s, stackPath.substring(last).removePrefix("/"))
@@ -1047,9 +1158,10 @@ class DeviceServicesActivity : BaseActivity() {
private fun showCharacteristicLoadingAnimation(barLabel: String) {
runOnUiThread {
- btn_bond_action.visibility = View.GONE
- tv_bond_state_with_rssi.visibility = View.GONE
- fly_in_bar.apply {
+ binding.btnBondAction.visibility = View.GONE
+
+ binding.tvBondStateWithRssi.visibility = View.GONE
+ binding.flyInBar.apply {
setOnClickListener { /* this onclicklistener prevents services and characteristics from user interaction before ui is loaded*/ }
visibility = View.VISIBLE
startFlyInAnimation(barLabel)
@@ -1059,17 +1171,22 @@ class DeviceServicesActivity : BaseActivity() {
private fun hideCharacteristicLoadingAnimation() {
runOnUiThread {
- fly_in_bar.startFlyOutAnimation(object : FlyInBar.Callback {
+
+ binding.flyInBar.startFlyOutAnimation(object : FlyInBar.Callback {
override fun onFlyOutAnimationEnded() {
- fly_in_bar.visibility = View.GONE
- btn_bond_action.visibility = View.VISIBLE
- tv_bond_state_with_rssi.visibility = View.VISIBLE
+ binding.flyInBar.visibility = View.GONE
+ binding.btnBondAction.visibility = View.VISIBLE
+ binding.tvBondStateWithRssi.visibility = View.VISIBLE
}
})
}
}
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_PERMISSION) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
@@ -1126,6 +1243,7 @@ class DeviceServicesActivity : BaseActivity() {
}
}
+ @SuppressLint("Range")
private fun getFileName(uri: Uri?): String? {
var result: String? = null
if ((uri?.scheme == "content")) {
@@ -1150,7 +1268,7 @@ class DeviceServicesActivity : BaseActivity() {
return filename?.toUpperCase(Locale.getDefault())?.contains(".GBL")!!
}
- private fun getDeviceName() : String {
+ private fun getDeviceName(): String {
return bluetoothDevice?.let {
if (TextUtils.isEmpty(it.name)) getString(R.string.not_advertising_shortcut)
else it.name
@@ -1211,7 +1329,8 @@ class DeviceServicesActivity : BaseActivity() {
private const val RECONNECTION_DELAY = 4000L // device needs to reboot
private const val OTA_CONTROL_START_DELAY = 200L // needed to avoid error status 135
private const val OTA_CONTROL_END_DELAY = 500L
- private const val CACHE_REFRESH_DELAY = 500L // no callback available, so give some time to refresh
+ private const val CACHE_REFRESH_DELAY =
+ 500L // no callback available, so give some time to refresh
private const val DIALOG_DELAY = 500L // give time for progress dialog to bind layout
private const val CONNECTION_REQUEST_DIALOG_FRAGMENT = "connection_request_dialog_fragment"
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/activities/UuidDictionaryActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/activities/UuidDictionaryActivity.kt
index d1de0d71..d4b5b8fe 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/activities/UuidDictionaryActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/activities/UuidDictionaryActivity.kt
@@ -6,18 +6,22 @@ import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
+import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.android.material.tabs.TabLayoutMediator
import com.siliconlabs.bledemo.features.scan.browser.dialogs.AboutUuidDictionaryDialog
import com.siliconlabs.bledemo.features.scan.browser.fragments.CharacteristicMappingsFragment
import com.siliconlabs.bledemo.features.scan.browser.fragments.ServiceMappingsFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.activity_uuid_dictionary.*
+import com.siliconlabs.bledemo.databinding.ActivityUuidDictionaryBinding
-class UuidDictionaryActivity : AppCompatActivity() {
+class UuidDictionaryActivity : AppCompatActivity() {
+ //private val binding by viewBinding(ActivityUuidDictionaryBinding::bind) //activity_uuid_dictionary
+ private lateinit var binding: ActivityUuidDictionaryBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_uuid_dictionary)
+ binding = ActivityUuidDictionaryBinding.inflate(layoutInflater)
+ setContentView(binding.root)
setupViewPager()
setupActionBar()
@@ -31,8 +35,12 @@ class UuidDictionaryActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.mappings_about -> {
- AboutUuidDictionaryDialog().show(supportFragmentManager, "about_mappings_dictionary_dialog")
+ AboutUuidDictionaryDialog().show(
+ supportFragmentManager,
+ "about_mappings_dictionary_dialog"
+ )
}
+
android.R.id.home -> onBackPressed()
else -> {
}
@@ -41,9 +49,11 @@ class UuidDictionaryActivity : AppCompatActivity() {
}
private fun setupViewPager() {
- view_pager2.adapter = ViewPagerAdapter()
- TabLayoutMediator(uuid_dictionary_tab_layout, view_pager2) { tab, position ->
+ binding.viewPager2.adapter = ViewPagerAdapter()
+
+
+ TabLayoutMediator(binding.uuidDictionaryTabLayout, binding.viewPager2) { tab, position ->
tab.text = when (position) {
0 -> getString(R.string.title_services)
1 -> getString(R.string.title_characteristics)
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/adapters/DebugModeDeviceAdapter.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/adapters/DebugModeDeviceAdapter.kt
index 1ad7e527..f658f2ae 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/adapters/DebugModeDeviceAdapter.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/adapters/DebugModeDeviceAdapter.kt
@@ -31,8 +31,8 @@ import java.util.concurrent.TimeUnit
import kotlin.math.roundToLong
class DebugModeDeviceAdapter(
- private var chosenDevices: MutableList,
- private val debugModeCallback: DebugModeCallback
+ private var chosenDevices: MutableList,
+ private val debugModeCallback: DebugModeCallback
) : RecyclerView.Adapter() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@@ -59,22 +59,37 @@ class DebugModeDeviceAdapter(
private fun setupUiListeners(holder: ViewHolder, viewBinding: AdapterBrowserDeviceBinding) {
viewBinding.apply {
- expandArrow.setOnClickListener { RecyclerViewUtils.withProperAdapterPosition(holder) { pos ->
- debugModeCallback.toggleViewExpansion(pos)
- } }
- connectionBtn.setOnClickListener { RecyclerViewUtils.withProperAdapterPosition(holder) { pos ->
- with(chosenDevices[pos].deviceInfo) {
- when (connectionState) {
- BluetoothDeviceInfo.ConnectionState.CONNECTED -> debugModeCallback.disconnectDevice(pos, this.device)
- BluetoothDeviceInfo.ConnectionState.DISCONNECTED -> debugModeCallback.connectToDevice(pos, this)
- else -> { }
+ expandArrow.setOnClickListener {
+ println("SICONNECT")
+ RecyclerViewUtils.withProperAdapterPosition(holder) { pos ->
+ debugModeCallback.toggleViewExpansion(pos)
+ }
+ }
+ connectionBtn.setOnClickListener {
+ RecyclerViewUtils.withProperAdapterPosition(holder) { pos ->
+ with(chosenDevices[pos].deviceInfo) {
+ when (connectionState) {
+ BluetoothDeviceInfo.ConnectionState.CONNECTED -> debugModeCallback.disconnectDevice(
+ pos,
+ this.device
+ )
+
+ BluetoothDeviceInfo.ConnectionState.DISCONNECTED -> debugModeCallback.connectToDevice(
+ pos,
+ this
+ )
+
+ else -> {}
+ }
}
}
- } }
- favoriteBtn.setOnClickListener { RecyclerViewUtils.withProperAdapterPosition(holder) { pos ->
- val clickedDevice = chosenDevices[pos].deviceInfo
- toggleFavoriteDevice(clickedDevice)
- } }
+ }
+ favoriteBtn.setOnClickListener {
+ RecyclerViewUtils.withProperAdapterPosition(holder) { pos ->
+ val clickedDevice = chosenDevices[pos].deviceInfo
+ toggleFavoriteDevice(clickedDevice)
+ }
+ }
}
}
@@ -83,17 +98,22 @@ class DebugModeDeviceAdapter(
notifyItemInserted(itemCount - 1)
}
- fun updateDevices(newList: List, withMoves: Boolean = false) {
- val listDiff = DiffUtil.calculateDiff(DiffCallback(
+ fun updateDevices(
+ newList: List,
+ withMoves: Boolean = false
+ ) {
+ val listDiff = DiffUtil.calculateDiff(
+ DiffCallback(
chosenDevices.toList(),
newList
- ), withMoves)
+ ), withMoves
+ )
chosenDevices = getDeepCopyList(newList).toMutableList()
listDiff.dispatchUpdatesTo(this)
}
- private fun getDeepCopyList(list: List) : List {
+ private fun getDeepCopyList(list: List): List {
return mutableListOf().apply {
list.forEach { add(it.copy(deviceInfo = it.deviceInfo.clone())) }
}
@@ -108,8 +128,8 @@ class DebugModeDeviceAdapter(
}
private class DiffCallback(
- private val oldList: List,
- private val newList: List
+ private val oldList: List,
+ private val newList: List
) : DiffUtil.Callback() {
override fun getOldListSize(): Int {
@@ -136,16 +156,16 @@ class DebugModeDeviceAdapter(
}
private class PayloadChange(
- val oldItem: ScanFragmentViewModel.BluetoothInfoViewState,
- val newItem: ScanFragmentViewModel.BluetoothInfoViewState
+ val oldItem: ScanFragmentViewModel.BluetoothInfoViewState,
+ val newItem: ScanFragmentViewModel.BluetoothInfoViewState
)
private class AdvertisementData(val rows: List>)
@SuppressLint("MissingPermission")
class ViewHolder(
- private val context: Context,
- private val viewBinding: AdapterBrowserDeviceBinding
+ private val context: Context,
+ private val viewBinding: AdapterBrowserDeviceBinding
) : RecyclerView.ViewHolder(viewBinding.root) {
fun bind(viewInfoState: ScanFragmentViewModel.BluetoothInfoViewState) {
@@ -155,16 +175,18 @@ class DebugModeDeviceAdapter(
viewBinding.apply {
manufacturerIcon.setImageDrawable(getManufacturerIcon(info.manufacturer))
deviceName.text =
- if (info.name.isEmpty()) itemView.context.getString(R.string.not_advertising_shortcut)
- else info.name
+ if (info.name.isEmpty()) itemView.context.getString(R.string.not_advertising_shortcut)
+ else info.name
tvDeviceAddress.text = context.getString(R.string.string_placeholder, info.address)
rssi.text = itemView.context.getString(R.string.unit_value_dbm, info.rssi)
- tvInterval.text = itemView.context.getString(R.string.unit_value_ms, info.intervalNanos / 1000000)
- deviceType.text = itemView.context.getString(info.bleFormat?.nameResId ?: R.string.unspecified)
+ tvInterval.text =
+ itemView.context.getString(R.string.unit_value_ms, info.intervalNanos / 1000000)
+ deviceType.text =
+ itemView.context.getString(info.bleFormat?.nameResId ?: R.string.unspecified)
tvIsConnectable.text = itemView.context.getString(
- if (info.isConnectable) R.string.connectible
- else R.string.non_connectible
+ if (info.isConnectable) R.string.connectible
+ else R.string.non_connectible
)
favoriteBtn.isChecked = info.isFavorite
tvIsBonded.text = getBondedStateText(info.device.bondState)
@@ -187,7 +209,8 @@ class DebugModeDeviceAdapter(
if (newInfo.rssi != oldInfo.rssi)
rssi.text = context.getString(R.string.unit_value_dbm, newInfo.rssi)
if (newInfo.intervalNanos != oldInfo.intervalNanos)
- tvInterval.text = context.getString(R.string.unit_value_ms, newInfo.intervalNanos / 1000000)
+ tvInterval.text =
+ context.getString(R.string.unit_value_ms, newInfo.intervalNanos / 1000000)
if (newInfo.device.bondState != oldInfo.device.bondState)
tvIsBonded.text = getBondedStateText(newInfo.device.bondState)
if (newInfo.connectionState != oldInfo.connectionState) {
@@ -197,10 +220,16 @@ class DebugModeDeviceAdapter(
favoriteBtn.isChecked = newInfo.isFavorite
}
if (oldInfo.rawData != newInfo.rawData) {
- deviceType.text = itemView.context.getString(newInfo.bleFormat?.nameResId ?: R.string.unspecified)
+ deviceType.text = itemView.context.getString(
+ newInfo.bleFormat?.nameResId ?: R.string.unspecified
+ )
manufacturerIcon.setImageDrawable(getManufacturerIcon(newInfo.manufacturer))
-
- if (newState.isInfoExpanded) addAdvertsDataToContainer(generateAdvertData(newInfo))
+ println("SiCONNECT --newState.isInfoExpanded:${newState.isInfoExpanded}")
+ if (newState.isInfoExpanded) addAdvertsDataToContainer(
+ generateAdvertData(
+ newInfo
+ )
+ )
}
}
}
@@ -210,11 +239,13 @@ class DebugModeDeviceAdapter(
if (deviceInfo.isConnectable) {
visibility = View.VISIBLE
setActionButtonState(deviceInfo.connectionState)
- text = context.getString( when (deviceInfo.connectionState) {
- BluetoothDeviceInfo.ConnectionState.CONNECTED -> R.string.button_disconnect
- BluetoothDeviceInfo.ConnectionState.CONNECTING -> R.string.button_connecting
- BluetoothDeviceInfo.ConnectionState.DISCONNECTED -> R.string.button_connect
- })
+ text = context.getString(
+ when (deviceInfo.connectionState) {
+ BluetoothDeviceInfo.ConnectionState.CONNECTED -> R.string.button_disconnect
+ BluetoothDeviceInfo.ConnectionState.CONNECTING -> R.string.button_connecting
+ BluetoothDeviceInfo.ConnectionState.DISCONNECTED -> R.string.button_connect
+ }
+ )
} else {
visibility = View.GONE
}
@@ -223,25 +254,29 @@ class DebugModeDeviceAdapter(
private fun toggleDetails(shouldShowDetails: Boolean) {
viewBinding.advertisementContainer.visibility =
- if (shouldShowDetails) View.VISIBLE
- else View.GONE
+ if (shouldShowDetails) View.VISIBLE
+ else View.GONE
viewBinding.expandArrow.setState(shouldShowDetails)
}
- private fun generateAdvertData(deviceInfo: BluetoothDeviceInfo) : AdvertisementData {
+ private fun generateAdvertData(deviceInfo: BluetoothDeviceInfo): AdvertisementData {
val rows: MutableList> = ArrayList()
if (!deviceInfo.scanInfo?.isLegacy!!) {
- rows.add(Pair(context.resources.getString(R.string.Bluetooth_5_Advertising_Extension),
- prepareBluetooth5AdvertExtensionData(deviceInfo.scanInfo!!)))
+ rows.add(
+ Pair(
+ context.resources.getString(R.string.Bluetooth_5_Advertising_Extension),
+ prepareBluetooth5AdvertExtensionData(deviceInfo.scanInfo!!)
+ )
+ )
}
deviceInfo.advertData.forEach {
val data = it?.split(ScanRecordParser.SPLIT.toRegex())?.toTypedArray()!!
val dataLabel = data[0]
val dataValue =
- if (data.size > 1) data[1]
- else ""
+ if (data.size > 1) data[1]
+ else ""
rows.add(Pair(dataLabel, dataValue))
}
@@ -249,49 +284,59 @@ class DebugModeDeviceAdapter(
BleFormat.I_BEACON -> iBeaconAdv(deviceInfo, rows)
BleFormat.EDDYSTONE -> eddystoneAdv(deviceInfo, rows)
BleFormat.ALT_BEACON -> altBeaconAdv(deviceInfo, rows)
- else -> { }
+ else -> {}
}
return AdvertisementData(rows)
}
- private fun getManufacturerIcon(manufacturer: BluetoothDeviceInfo.DeviceManufacturer) : Drawable? {
- return ContextCompat.getDrawable(context, when (manufacturer) {
- BluetoothDeviceInfo.DeviceManufacturer.WINDOWS -> R.drawable.redesign_ic_scanned_device_windows
- BluetoothDeviceInfo.DeviceManufacturer.UNKNOWN -> R.drawable.redesign_ic_bluetooth_with_background
- })
+ private fun getManufacturerIcon(manufacturer: BluetoothDeviceInfo.DeviceManufacturer): Drawable? {
+ return ContextCompat.getDrawable(
+ context, when (manufacturer) {
+ BluetoothDeviceInfo.DeviceManufacturer.WINDOWS -> R.drawable.redesign_ic_scanned_device_windows
+ BluetoothDeviceInfo.DeviceManufacturer.UNKNOWN -> R.drawable.redesign_ic_bluetooth_with_background
+ }
+ )
}
- private fun getBondedStateText(bondState: Int) : String {
+ private fun getBondedStateText(bondState: Int): String {
return context.getString(
- if (bondState == BluetoothDevice.BOND_BONDED) R.string.scanned_device_bonded
- else R.string.scanned_device_not_bonded
+ if (bondState == BluetoothDevice.BOND_BONDED) R.string.scanned_device_bonded
+ else R.string.scanned_device_not_bonded
)
}
private fun prepareBluetooth5AdvertExtensionData(scanResult: ScanResultCompat): String {
return StringBuilder().apply {
append(context.getString(R.string.Data_Status_colon))
- append(context.getString(
+ append(
+ context.getString(
if (scanResult.dataStatus == 0) R.string.advertising_extension_status_complete
else R.string.advertising_extension_status_truncated
- ))
+ )
+ )
append("
")
append(context.getString(R.string.Primary_PHY_colon))
- append(context.getString(
+ append(
+ context.getString(
if (scanResult.primaryPhy == 1) R.string.advertising_extension_phy_le_1m
else R.string.advertising_extension_phy_le_coded
- ))
+ )
+ )
append("
")
append(context.getString(R.string.Secondary_PHY_colon))
- append(context.getString(when (scanResult.secondaryPhy) {
- 1 -> R.string.advertising_extension_phy_le_1m
- 2 -> R.string.advertising_extension_phy_le_2m
- 3 -> R.string.advertising_extension_phy_le_coded
- else -> R.string.advertising_extension_phy_unused
- }))
+ append(
+ context.getString(
+ when (scanResult.secondaryPhy) {
+ 1 -> R.string.advertising_extension_phy_le_1m
+ 2 -> R.string.advertising_extension_phy_le_2m
+ 3 -> R.string.advertising_extension_phy_le_coded
+ else -> R.string.advertising_extension_phy_unused
+ }
+ )
+ )
append("
")
append(context.getString(R.string.Advertising_Set_ID))
@@ -314,16 +359,35 @@ class DebugModeDeviceAdapter(
}.toString()
}
- private fun validateEddyStoneServiceData(beacon: Beacon, deviceAddress: String, serviceData: ByteArray?) {
+ private fun validateEddyStoneServiceData(
+ beacon: Beacon,
+ deviceAddress: String,
+ serviceData: ByteArray?
+ ) {
if (serviceData == null) {
val err = "Null Eddystone service data"
beacon.frameStatus.nullServiceData = err
return
}
when (serviceData[0]) {
- Constants.UID_FRAME_TYPE -> UidValidator.validate(deviceAddress, serviceData, beacon)
- Constants.TLM_FRAME_TYPE -> TlmValidator.validate(deviceAddress, serviceData, beacon)
- Constants.URL_FRAME_TYPE -> UrlValidator.validate(deviceAddress, serviceData, beacon)
+ Constants.UID_FRAME_TYPE -> UidValidator.validate(
+ deviceAddress,
+ serviceData,
+ beacon
+ )
+
+ Constants.TLM_FRAME_TYPE -> TlmValidator.validate(
+ deviceAddress,
+ serviceData,
+ beacon
+ )
+
+ Constants.URL_FRAME_TYPE -> UrlValidator.validate(
+ deviceAddress,
+ serviceData,
+ beacon
+ )
+
else -> {
val err = String.format("Invalid frame type byte %02X", serviceData[0])
beacon.frameStatus.invalidFrameType = err
@@ -337,24 +401,31 @@ class DebugModeDeviceAdapter(
val title = it.first
val text = Html.fromHtml(it.second).toString()
val serviceItemContainer = DetailsRow(context, title, text)
- viewBinding.advertisementContainer.addView(serviceItemContainer,
+ viewBinding.advertisementContainer.addView(serviceItemContainer.binding.root,
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
}
}
- private fun iBeaconAdv(deviceInfo: BluetoothDeviceInfo, rows: MutableList>) {
- IBeaconInfo.getIBeaconInfo(deviceInfo.scanInfo?.scanRecord?.bytes!!)?.let { beaconInfo ->
- val info = StringBuilder().apply {
- append("Minor: ").append(beaconInfo.minor).append("
")
- append("Major: ").append(beaconInfo.major).append("
")
- append("UUID: ").append(beaconInfo.uuid).append("
")
- append("RSSI at 1m: ").append(beaconInfo.power)
- }.toString()
- rows.add(Pair("iBeacon data", info))
- }
+ private fun iBeaconAdv(
+ deviceInfo: BluetoothDeviceInfo,
+ rows: MutableList>
+ ) {
+ IBeaconInfo.getIBeaconInfo(deviceInfo.scanInfo?.scanRecord?.bytes!!)
+ ?.let { beaconInfo ->
+ val info = StringBuilder().apply {
+ append("Minor: ").append(beaconInfo.minor).append("
")
+ append("Major: ").append(beaconInfo.major).append("
")
+ append("UUID: ").append(beaconInfo.uuid).append("
")
+ append("RSSI at 1m: ").append(beaconInfo.power)
+ }.toString()
+ rows.add(Pair("iBeacon data", info))
+ }
}
- private fun eddystoneAdv(deviceInfo: BluetoothDeviceInfo, rows: MutableList>) {
+ private fun eddystoneAdv(
+ deviceInfo: BluetoothDeviceInfo,
+ rows: MutableList>
+ ) {
var dataValue = ""
val scanInfo = deviceInfo.scanInfo
val deviceAddress = scanInfo?.device?.address
@@ -364,13 +435,21 @@ class DebugModeDeviceAdapter(
// get url string
var eddystoneUrl = beacon.urlStatus.toString()
- eddystoneUrl = if (TextUtils.isEmpty(eddystoneUrl)) context.getString(R.string.beacon_details_dialog_unknown_value) else eddystoneUrl
+ eddystoneUrl =
+ if (TextUtils.isEmpty(eddystoneUrl)) context.getString(R.string.beacon_details_dialog_unknown_value) else eddystoneUrl
// get uid string
// Eddystone UID Advertisement Data: 16-byte Beacon ID (10-byte namespace, 6-byte instance)
val eddystoneUid = beacon.uidStatus.uidValue
- val eddystoneUidValue = if (TextUtils.isEmpty(eddystoneUid)) context.getString(R.string.beacon_details_dialog_unknown_value) else eddystoneUid?.substring(0, 20)
- val eddystoneUidNameSpace = if (TextUtils.isEmpty(eddystoneUid)) context.getString(R.string.beacon_details_dialog_unknown_value) else "" + eddystoneUid?.substring(20)
+ val eddystoneUidValue =
+ if (TextUtils.isEmpty(eddystoneUid)) context.getString(R.string.beacon_details_dialog_unknown_value) else eddystoneUid?.substring(
+ 0,
+ 20
+ )
+ val eddystoneUidNameSpace =
+ if (TextUtils.isEmpty(eddystoneUid)) context.getString(R.string.beacon_details_dialog_unknown_value) else "" + eddystoneUid?.substring(
+ 20
+ )
// get tlm data
val version = beacon.tlmStatus.version
@@ -379,18 +458,22 @@ class DebugModeDeviceAdapter(
var voltageValue = 0.0
if (voltage != null) {
voltageValue = voltage.toDouble()
- voltage = (voltageValue / 1000).toString() + " " + context.getString(R.string.beacon_details_dialog_unit_volts)
+ voltage =
+ (voltageValue / 1000).toString() + " " + context.getString(R.string.beacon_details_dialog_unit_volts)
}
val temperature = beacon.tlmStatus.temp + " " +
context.getString(R.string.beacon_details_dialog_unit_degrees_celsius)
val advertisementCount = beacon.tlmStatus.advCnt
var uptimeCountInSeconds = beacon.tlmStatus.deciSecondsCntVal / 10
uptimeCountInSeconds = Math.round(uptimeCountInSeconds * 10) / 10.0
- val secondsLabel = context.getString(R.string.beacon_details_dialog_unit_seconds_abbreviated)
+ val secondsLabel =
+ context.getString(R.string.beacon_details_dialog_unit_seconds_abbreviated)
val daysLabel = context.getString(R.string.beacon_details_dialog_unit_days)
- val uptimeCount = String.format("%d $secondsLabel (%d $daysLabel)",
- uptimeCountInSeconds.toInt(),
- TimeUnit.SECONDS.toDays(uptimeCountInSeconds.roundToLong()))
+ val uptimeCount = String.format(
+ "%d $secondsLabel (%d $daysLabel)",
+ uptimeCountInSeconds.toInt(),
+ TimeUnit.SECONDS.toDays(uptimeCountInSeconds.roundToLong())
+ )
var eddystoneTlm = ""
eddystoneTlm += context.getString(R.string.beacon_details_dialog_tlm_version) + ": " + version + "
"
eddystoneTlm += context.getString(R.string.beacon_details_dialog_tlm_voltage) + ": " + voltage + "
"
@@ -399,7 +482,8 @@ class DebugModeDeviceAdapter(
eddystoneTlm += context.getString(R.string.beacon_details_dialog_tlm_advertisement_count) + ": " +
advertisementCount + "
"
eddystoneTlm += context.getString(R.string.beacon_details_dialog_tlm_uptime) + ": " + uptimeCount
- eddystoneTlm = if (TextUtils.isEmpty(eddystoneTlm)) context.getString(R.string.beacon_details_dialog_unknown_value) else eddystoneTlm
+ eddystoneTlm =
+ if (TextUtils.isEmpty(eddystoneTlm)) context.getString(R.string.beacon_details_dialog_unknown_value) else eddystoneTlm
dataValue += context.getString(R.string.beacon_details_dialog_url) + ": " + eddystoneUrl + "
"
dataValue += context.getString(R.string.beacon_details_dialog_uid) + ": " + eddystoneUidValue +
"
"
@@ -410,7 +494,10 @@ class DebugModeDeviceAdapter(
rows.add(Pair("Eddystone data", dataValue))
}
- private fun altBeaconAdv(deviceInfo: BluetoothDeviceInfo, rows: MutableList>) {
+ private fun altBeaconAdv(
+ deviceInfo: BluetoothDeviceInfo,
+ rows: MutableList>
+ ) {
val altBeacon = AltBeacon(deviceInfo)
val beaconId = altBeacon.altBeaconId
@@ -421,10 +508,14 @@ class DebugModeDeviceAdapter(
append(context.getString(R.string.beacon_details_dialog_beacon_id)).append("
")
append(beaconId).append("
")
- append(context.getString(R.string.beacon_details_dialog_manufacturer_id)).append(mfgId)
+ append(context.getString(R.string.beacon_details_dialog_manufacturer_id)).append(
+ mfgId
+ )
append("
")
- append(context.getString(R.string.beacon_details_dialog_reference_rssi)).append(refRssi)
+ append(context.getString(R.string.beacon_details_dialog_reference_rssi)).append(
+ refRssi
+ )
append(" dBm
") //non-breaking space in HTML to separate value with a unit (dBm)
}.toString()
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/AboutUuidDictionaryDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/AboutUuidDictionaryDialog.kt
index 788b6a54..87b05dc3 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/AboutUuidDictionaryDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/AboutUuidDictionaryDialog.kt
@@ -4,22 +4,30 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import by.kirich1409.viewbindingdelegate.viewBinding
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_about_uuid_dictionary.*
+import com.siliconlabs.bledemo.databinding.DialogAboutUuidDictionaryBinding
+
class AboutUuidDictionaryDialog : BaseDialogFragment(
- hasCustomWidth = true,
- isCanceledOnTouchOutside = true
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = true
) {
+ private lateinit var binding: DialogAboutUuidDictionaryBinding //dialog_about_uuid_dictionary
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_about_uuid_dictionary, container, false)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogAboutUuidDictionaryBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- btn_ok.setOnClickListener { dismiss() }
+ binding.btnOk.setOnClickListener { dismiss() }
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/ErrorDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/ErrorDialog.kt
index 9315649a..514e459f 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/ErrorDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/ErrorDialog.kt
@@ -9,29 +9,36 @@ import android.view.ViewGroup
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.bluetooth.ble.ErrorCodes.getATTHTMLFormattedError
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_error.*
+import com.siliconlabs.bledemo.databinding.DialogErrorBinding
+
class ErrorDialog(
- private val errorCode: Int,
- private val otaErrorCallback: OtaErrorCallback
+ private val errorCode: Int,
+ private val otaErrorCallback: OtaErrorCallback
) : BaseDialogFragment(
- hasCustomWidth = true,
- isCanceledOnTouchOutside = false
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = false
) {
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_error, container, false)
+ private lateinit var binding: DialogErrorBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogErrorBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
-
- btn_ok.setOnClickListener {
+ binding.btnOk.setOnClickListener {
dismiss()
otaErrorCallback.onDismiss()
}
- error_description.text = Html.fromHtml(getATTHTMLFormattedError(errorCode))
+ binding.errorDescription
+ .text = Html.fromHtml(getATTHTMLFormattedError(errorCode))
}
override fun onDismiss(dialog: DialogInterface) {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/LeaveApplicationDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/LeaveApplicationDialog.kt
index 4283d22b..25db7951 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/LeaveApplicationDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/LeaveApplicationDialog.kt
@@ -6,32 +6,43 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.DialogInfoOkCancelBinding
import com.siliconlabs.bledemo.utils.SharedPrefUtils
-import kotlinx.android.synthetic.main.dialog_info_ok_cancel.*
+
class LeaveApplicationDialog(var callback: Callback) : BaseDialogFragment() {
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_info_ok_cancel, container, false)
+ private lateinit var binding: DialogInfoOkCancelBinding //dialog_info_ok_cancel
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogInfoOkCancelBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- tv_dialog_title.text = context?.getString(R.string.Leave_Application)
- tv_dialog_content.text = context?.getString(R.string.leave_application_info)
+ binding.tvDialogTitle
+ .text = context?.getString(R.string.Leave_Application)
+ binding.tvDialogContent
+ .text = context?.getString(R.string.leave_application_info)
handleClickEvents()
}
private fun handleClickEvents() {
- btn_ok.setOnClickListener {
- if (cb_dont_show_again.isChecked) SharedPrefUtils(requireContext()).setShouldLeaveApplicationDialog(false)
+ binding.btnOk.setOnClickListener {
+ if (binding.cbDontShowAgain.isChecked) SharedPrefUtils(requireContext()).setShouldLeaveApplicationDialog(
+ false
+ )
callback.onOkClicked()
dismiss()
}
- btn_cancel.setOnClickListener {
+ binding.btnCancel.setOnClickListener {
dismiss()
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/ManualUnbondDeviceDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/ManualUnbondDeviceDialog.kt
index e534b169..5bab1285 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/ManualUnbondDeviceDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/ManualUnbondDeviceDialog.kt
@@ -6,25 +6,39 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.DialogInfoOkCancelBinding
import com.siliconlabs.bledemo.utils.SharedPrefUtils
-import kotlinx.android.synthetic.main.dialog_info_ok_cancel.view.*
+
class ManualUnbondDeviceDialog(val callback: Callback) : BaseDialogFragment() {
+ private lateinit var binding: DialogInfoOkCancelBinding//dialog_info_ok_cancel
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogInfoOkCancelBinding.inflate(inflater, container, false).apply {
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_info_ok_cancel, container, false).apply {
+ binding.tvDialogTitle.text =
+ requireContext().getString(R.string.device_services_title_unbond_device_manual)
+ binding.tvDialogContent.text =
+ requireContext().getString(R.string.device_services_note_unbond_device_manual)
- tv_dialog_title.text = context.getString(R.string.device_services_title_unbond_device_manual)
- tv_dialog_content.text = context.getString(R.string.device_services_note_unbond_device_manual)
- btn_ok.text = context.getString(R.string.button_proceed)
+ binding.btnOk.text = requireContext().getString(R.string.button_proceed)
- btn_ok.setOnClickListener {
- if (cb_dont_show_again.isChecked) SharedPrefUtils(requireContext()).setShouldDisplayManualUnbondDeviceDialog(false)
+ binding.btnOk.setOnClickListener {
+ if (binding.cbDontShowAgain
+ .isChecked) SharedPrefUtils(requireContext()).setShouldDisplayManualUnbondDeviceDialog(
+ false
+ )
callback.onOkClicked()
dismiss()
}
- btn_cancel.setOnClickListener { dismiss() }
+ binding.btnCancel.setOnClickListener { dismiss() }
}
+
+ return binding.root
}
interface Callback {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/OtaCharacteristicMissingDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/OtaCharacteristicMissingDialog.kt
index 82806fd7..03a0bf2b 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/OtaCharacteristicMissingDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/OtaCharacteristicMissingDialog.kt
@@ -6,21 +6,26 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
-import kotlinx.android.synthetic.main.dialog_ota_missing_characteristic.*
+import com.siliconlabs.bledemo.databinding.DialogOtaMissingCharacteristicBinding
+
class OtaCharacteristicMissingDialog : BaseDialogFragment(
- hasCustomWidth = true,
- isCanceledOnTouchOutside = true
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = true
) {
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_ota_missing_characteristic, null)
+ private lateinit var binding: DialogOtaMissingCharacteristicBinding//dialog_ota_missing_characteristic
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogOtaMissingCharacteristicBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- button_ok.setOnClickListener { dismiss() }
+ binding.buttonOk.setOnClickListener { dismiss() }
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/UnbondDeviceDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/UnbondDeviceDialog.kt
index f96e8a14..06e78cce 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/UnbondDeviceDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/dialogs/UnbondDeviceDialog.kt
@@ -6,24 +6,37 @@ import android.view.View
import android.view.ViewGroup
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.DialogInfoOkCancelBinding
import com.siliconlabs.bledemo.utils.SharedPrefUtils
-import kotlinx.android.synthetic.main.dialog_info_ok_cancel.view.*
+
class UnbondDeviceDialog(val callback: Callback) : BaseDialogFragment() {
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.dialog_info_ok_cancel, container, false).apply {
+ private lateinit var binding: DialogInfoOkCancelBinding//dialog_info_ok_cancel
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = DialogInfoOkCancelBinding.inflate(inflater, container, false).apply {
- tv_dialog_title.text = context.getString(R.string.device_services_title_unbond_device)
- tv_dialog_content.text = context.getString(R.string.device_services_note_unbond_device)
+ tvDialogTitle.text =
+ requireContext().getString(R.string.device_services_title_unbond_device)
+ tvDialogContent.text =
+ requireContext().getString(R.string.device_services_note_unbond_device)
- btn_ok.setOnClickListener {
- if (cb_dont_show_again.isChecked) SharedPrefUtils(requireContext()).setShouldDisplayUnbondDeviceDialog(false)
- callback.onOkClicked()
- dismiss()
- }
- btn_cancel.setOnClickListener { dismiss() }
+ btnOk
+ .setOnClickListener {
+ if (cbDontShowAgain.isChecked) SharedPrefUtils(requireContext()).setShouldDisplayUnbondDeviceDialog(
+ false
+ )
+ callback.onOkClicked()
+ dismiss()
+ }
+ btnCancel.setOnClickListener { dismiss() }
}
+ return binding.root
}
interface Callback {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/BrowserFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/BrowserFragment.kt
index addf5977..11dc96ef 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/BrowserFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/BrowserFragment.kt
@@ -52,7 +52,8 @@ import com.siliconlabs.bledemo.home_screen.viewmodels.ScanFragmentViewModel
import com.siliconlabs.bledemo.features.scan.browser.adapters.DebugModeCallback
import com.siliconlabs.bledemo.home_screen.base.BluetoothDependent
import com.siliconlabs.bledemo.home_screen.base.LocationDependent
-import kotlinx.android.synthetic.main.fragment_browser.view.*
+import com.siliconlabs.bledemo.home_screen.base.NotificationDependent
+
class BrowserFragment : BaseServiceDependentMainMenuFragment(),
OnRefreshListener {
@@ -126,6 +127,7 @@ class BrowserFragment : BaseServiceDependentMainMenuFragment(),
}
}
+
private val scanFragmentListener = object: ScanFragment.ScanFragmentListener{
override fun onScanningStateChanged(isOn: Boolean) {
toggleMainView(isOn, viewModel.isAnyDeviceDiscovered.value ?: false)
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/CharacteristicMappingsFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/CharacteristicMappingsFragment.kt
index 516f90f9..d16e5983 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/CharacteristicMappingsFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/CharacteristicMappingsFragment.kt
@@ -10,8 +10,9 @@ import com.siliconlabs.bledemo.features.scan.browser.adapters.DictionaryEntryAda
import com.siliconlabs.bledemo.features.scan.browser.models.Mapping
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.common.other.CardViewListDecoration
+import com.siliconlabs.bledemo.databinding.FragmentCharacteristicMappingsBinding
import com.siliconlabs.bledemo.utils.SharedPrefUtils
-import kotlinx.android.synthetic.main.fragment_characteristic_mappings.*
+
import java.util.*
import kotlin.collections.ArrayList
@@ -19,6 +20,7 @@ class CharacteristicMappingsFragment : Fragment() {
private lateinit var map: HashMap
private lateinit var list: ArrayList
private lateinit var sharedPrefUtils: SharedPrefUtils
+ private lateinit var binding: FragmentCharacteristicMappingsBinding //fragment_characteristic_mappings
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -27,16 +29,22 @@ class CharacteristicMappingsFragment : Fragment() {
list = ArrayList(map.values)
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.fragment_characteristic_mappings, container, false)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentCharacteristicMappingsBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- rv_characteristics.apply {
+ binding.rvCharacteristics.apply {
layoutManager = LinearLayoutManager(activity)
addItemDecoration(CardViewListDecoration())
- adapter = DictionaryEntryAdapter(list, requireContext(), Mapping.Type.CHARACTERISTIC)
+ adapter =
+ DictionaryEntryAdapter(list, requireContext(), Mapping.Type.CHARACTERISTIC)
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/FilterFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/FilterFragment.kt
index dc841ee2..9d6409a6 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/FilterFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/FilterFragment.kt
@@ -11,7 +11,7 @@ import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.databinding.FragmentFilterBinding
import com.siliconlabs.bledemo.home_screen.fragments.ScanFragment
import com.siliconlabs.bledemo.utils.FilterDeviceParams
-import kotlinx.android.synthetic.main.fragment_filter.*
+//import kotlinx.android.synthetic.main.fragment_filter.*
import java.util.*
class FilterFragment : DialogFragment() {
@@ -25,7 +25,11 @@ class FilterFragment : DialogFragment() {
viewModel = (parentFragment as ScanFragment).viewModel
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
setHasOptionsMenu(true)
viewBinding = FragmentFilterBinding.inflate(inflater)
return viewBinding.root
@@ -50,6 +54,7 @@ class FilterFragment : DialogFragment() {
resetFilters()
true
}
+
else -> super.onOptionsItemSelected(item)
}
}
@@ -72,10 +77,13 @@ class FilterFragment : DialogFragment() {
seekBarRssi.seekControlBar.progress = getSeekbarProgress(it.rssiValue)
seekBarRssi.seekControlText.text = getString(R.string.n_dBm, it.rssiValue)
}
- if (it.bleFormats.contains(BleFormat.UNSPECIFIED)) beaconTypeUnspecified.isChecked = true
- if (it.bleFormats.contains(BleFormat.ALT_BEACON)) beaconTypeAltBeacon.isChecked = true
+ if (it.bleFormats.contains(BleFormat.UNSPECIFIED)) beaconTypeUnspecified.isChecked =
+ true
+ if (it.bleFormats.contains(BleFormat.ALT_BEACON)) beaconTypeAltBeacon.isChecked =
+ true
if (it.bleFormats.contains(BleFormat.I_BEACON)) beaconTypeIBeacon.isChecked = true
- if (it.bleFormats.contains(BleFormat.EDDYSTONE)) beaconTypeEddystone.isChecked = true
+ if (it.bleFormats.contains(BleFormat.EDDYSTONE)) beaconTypeEddystone.isChecked =
+ true
if (it.isOnlyConnectable) cbOnlyConnectable.isChecked = true
if (it.isOnlyBonded) cbOnlyBonded.isChecked = true
@@ -117,7 +125,8 @@ class FilterFragment : DialogFragment() {
}
}
- seekBarRssi.seekControlBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+ seekBarRssi.seekControlBar.setOnSeekBarChangeListener(object :
+ SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
rssiFlag = true
val rssi = getRssiValue(progress)
@@ -134,7 +143,7 @@ class FilterFragment : DialogFragment() {
return progress - requireContext().resources.getInteger(R.integer.rssi_value_range)
}
- private fun getSeekbarProgress(rssiValue: Int) : Int {
+ private fun getSeekbarProgress(rssiValue: Int): Int {
return rssiValue + requireContext().resources.getInteger(R.integer.rssi_value_range)
}
@@ -154,13 +163,13 @@ class FilterFragment : DialogFragment() {
val name = viewBinding.etSearchDeviceName.text.toString()
val rssi = getRssiValue(viewBinding.seekBarRssi.seekControlBar.progress)
val activeFilter = FilterDeviceParams(
- if (name.isNotBlank()) name else null,
- rssi,
- rssiFlag,
- selectedBeacons,
- cb_only_favourites.isChecked,
- cb_only_connectable.isChecked,
- cb_only_bonded.isChecked
+ if (name.isNotBlank()) name else null,
+ rssi,
+ rssiFlag,
+ selectedBeacons,
+ viewBinding.cbOnlyFavourites.isChecked,
+ viewBinding.cbOnlyConnectable.isChecked,
+ viewBinding.cbOnlyBonded.isChecked
)
return if (!activeFilter.isEmpty) activeFilter else null
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/RemoteServicesFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/RemoteServicesFragment.kt
index 2da76457..869b30e1 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/RemoteServicesFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/RemoteServicesFragment.kt
@@ -11,10 +11,9 @@ import androidx.core.content.ContextCompat
import androidx.core.widget.ImageViewCompat
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.databinding.PropertyContainerBinding
-import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Property
import com.siliconlabs.bledemo.utils.BLEUtils
import com.siliconlabs.bledemo.utils.Notifications
-import kotlinx.android.synthetic.main.fragment_services.view.*
+
@SuppressLint("MissingPermission")
class RemoteServicesFragment(private val onScrollChangeListener: View.OnScrollChangeListener) : ServicesFragment(isRemote = true) {
@@ -23,7 +22,8 @@ class RemoteServicesFragment(private val onScrollChangeListener: View.OnScrollCh
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- binding.swipeRefreshContainer.scrollview.setOnScrollChangeListener(onScrollChangeListener)
+ // binding.swipeRefreshContainer.scrollview.setOnScrollChangeListener(onScrollChangeListener)
+ binding.swipeRefreshContainer.setOnScrollChangeListener(onScrollChangeListener)
}
override fun readCharacteristic(bluetoothGattCharacteristic: BluetoothGattCharacteristic) {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/ServiceMappingsFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/ServiceMappingsFragment.kt
index a8eccd78..b90fd98a 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/ServiceMappingsFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/ServiceMappingsFragment.kt
@@ -10,8 +10,9 @@ import com.siliconlabs.bledemo.features.scan.browser.adapters.DictionaryEntryAda
import com.siliconlabs.bledemo.features.scan.browser.models.Mapping
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.common.other.CardViewListDecoration
+import com.siliconlabs.bledemo.databinding.FragmentServiceMappingsBinding
+import com.siliconlabs.bledemo.databinding.FragmentServicesBinding
import com.siliconlabs.bledemo.utils.SharedPrefUtils
-import kotlinx.android.synthetic.main.fragment_service_mappings.*
import java.util.*
import kotlin.collections.ArrayList
@@ -19,6 +20,7 @@ class ServiceMappingsFragment : Fragment() {
private lateinit var map: HashMap
private lateinit var list: ArrayList
private lateinit var sharedPrefUtils: SharedPrefUtils
+ private lateinit var binding: FragmentServiceMappingsBinding //fragment_service_mappings
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -27,13 +29,18 @@ class ServiceMappingsFragment : Fragment() {
list = ArrayList(map.values)
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.fragment_service_mappings, container, false)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentServiceMappingsBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- rv_services.apply {
+ binding.rvServices.apply {
layoutManager = LinearLayoutManager(activity)
addItemDecoration(CardViewListDecoration())
adapter = DictionaryEntryAdapter(list, requireContext(), Mapping.Type.SERVICE)
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/ServicesFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/ServicesFragment.kt
index 47d571a1..added969 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/ServicesFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/browser/fragments/ServicesFragment.kt
@@ -10,23 +10,23 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
+import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.bluetooth.parsing.DescriptorParser
+import com.siliconlabs.bledemo.databinding.FragmentServicesBinding
+import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Property
+import com.siliconlabs.bledemo.features.iop_test.models.CommonUUID
import com.siliconlabs.bledemo.features.scan.browser.activities.DeviceServicesActivity
-import com.siliconlabs.bledemo.features.scan.browser.dialogs.DictionaryEntryEditDialog
import com.siliconlabs.bledemo.features.scan.browser.adapters.MappingCallback
+import com.siliconlabs.bledemo.features.scan.browser.dialogs.DictionaryEntryEditDialog
import com.siliconlabs.bledemo.features.scan.browser.models.Mapping
-import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.features.scan.browser.views.CharacteristicItemContainer
import com.siliconlabs.bledemo.features.scan.browser.views.DescriptorContainer
import com.siliconlabs.bledemo.features.scan.browser.views.ServiceItemContainer
-import com.siliconlabs.bledemo.databinding.FragmentServicesBinding
-import com.siliconlabs.bledemo.features.configure.gatt_configurator.models.Property
-import com.siliconlabs.bledemo.features.iop_test.models.CommonUUID
import com.siliconlabs.bledemo.utils.*
-import kotlinx.android.synthetic.main.descriptor_container.view.*
import java.util.*
-abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layout.fragment_services) {
+abstract class ServicesFragment(private val isRemote: Boolean) :
+ Fragment(R.layout.fragment_services) {
protected lateinit var binding: FragmentServicesBinding
@@ -40,9 +40,11 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
protected var currentWriteReadFragment: FragmentCharacteristicDetail? = null
private val descriptorsMap = mutableMapOf()
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View? {
- binding = FragmentServicesBinding.inflate(inflater)
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentServicesBinding.inflate(inflater, container, false)
return binding.root
}
@@ -62,10 +64,10 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
(activity as DeviceServicesActivity).refreshServices()
}
setColorSchemeColors(
- ContextCompat.getColor(requireContext(), android.R.color.holo_red_dark),
- ContextCompat.getColor(requireContext(), android.R.color.holo_orange_dark),
- ContextCompat.getColor(requireContext(), android.R.color.holo_orange_light),
- ContextCompat.getColor(requireContext(), android.R.color.holo_red_light)
+ ContextCompat.getColor(requireContext(), android.R.color.holo_red_dark),
+ ContextCompat.getColor(requireContext(), android.R.color.holo_orange_dark),
+ ContextCompat.getColor(requireContext(), android.R.color.holo_orange_light),
+ ContextCompat.getColor(requireContext(), android.R.color.holo_red_light)
)
}
}
@@ -82,11 +84,20 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
binding.servicesContainer.removeAllViews()
}
+// fun updateDescriptorView(descriptor: BluetoothGattDescriptor) {
+// descriptorsMap[descriptor]?.apply {
+// activity?.runOnUiThread {
+//
+// container_descriptor_value.visibility = View.VISIBLE
+// tv_value.text = DescriptorParser(descriptor).getFormattedValue()
+// }
+// }
+// }
+ //TODO
fun updateDescriptorView(descriptor: BluetoothGattDescriptor) {
descriptorsMap[descriptor]?.apply {
activity?.runOnUiThread {
- container_descriptor_value.visibility = View.VISIBLE
- tv_value.text = DescriptorParser(descriptor).getFormattedValue()
+
}
}
}
@@ -125,20 +136,23 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
private val characteristicContainerCallback = object : CharacteristicItemContainer.Callback {
override fun onRenameClicked(container: CharacteristicItemContainer) {
- DictionaryEntryEditDialog(
- container.getCharacteristicName(),
- UuidUtils.getUuidText(container.characteristic.uuid),
- Mapping.Type.CHARACTERISTIC,
- object : MappingCallback {
- override fun onNameChanged(mapping: Mapping) {
- container.setCharacteristicName(mapping.name)
- characteristicNamesMap[mapping.uuid] = mapping
- }
- }
- ).show(parentFragmentManager, "dialog_mapping_edit")
+ DictionaryEntryEditDialog(
+ container.getCharacteristicName(),
+ UuidUtils.getUuidText(container.characteristic.uuid),
+ Mapping.Type.CHARACTERISTIC,
+ object : MappingCallback {
+ override fun onNameChanged(mapping: Mapping) {
+ container.setCharacteristicName(mapping.name)
+ characteristicNamesMap[mapping.uuid] = mapping
+ }
+ }
+ ).show(parentFragmentManager, "dialog_mapping_edit")
}
- override fun onPropertyClicked(property: Property, characteristicContainer: CharacteristicItemContainer) {
+ override fun onPropertyClicked(
+ property: Property,
+ characteristicContainer: CharacteristicItemContainer
+ ) {
handleOnPropertyClicked(property, characteristicContainer)
}
}
@@ -153,29 +167,29 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
context?.let {
services.forEachIndexed { position, service ->
val serviceItemContainer = ServiceItemContainer(
- it,
- serviceContainerCallback,
- service,
- isMandatorySystemService(service.uuid),
- serviceNamesMap
+ it,
+ serviceContainerCallback,
+ service,
+ isMandatorySystemService(service.uuid),
+ serviceNamesMap
)
service.characteristics.forEach { char ->
val characteristicContainer = CharacteristicItemContainer(
- it,
- characteristicContainerCallback,
- char,
- isMandatorySystemService(service.uuid),
- characteristicNamesMap
+ it,
+ characteristicContainerCallback,
+ char,
+ isMandatorySystemService(service.uuid),
+ characteristicNamesMap
)
if (char.descriptors.isEmpty()) characteristicContainer.hideDescriptorsContainer()
else {
char.descriptors.forEach { descriptor ->
DescriptorContainer(
- it,
- descriptorContainerCallback,
- descriptor
+ it,
+ descriptorContainerCallback,
+ descriptor
).also {
characteristicContainer.addDescriptorContainer(it)
descriptorsMap[descriptor] = it
@@ -187,23 +201,24 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
serviceItemContainer.setMargins(position)
binding.servicesContainer.addView(
- serviceItemContainer,
- LinearLayout.LayoutParams.MATCH_PARENT,
- LinearLayout.LayoutParams.WRAP_CONTENT
+ serviceItemContainer,
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
)
}
- (activity as? DeviceServicesActivity)?.isUiCreated = true // prevent from crashes when clicking "back" when still loading
+ (activity as? DeviceServicesActivity)?.isUiCreated =
+ true // prevent from crashes when clicking "back" when still loading
}
}
- private fun initFragmentCharacteristicDetail(
- bluetoothGattCharacteristic: BluetoothGattCharacteristic,
- expansionId: Int,
- service: BluetoothGattService,
- characteristicExpansion: LinearLayout,
- displayWriteDialog: Boolean = false,
- writeType: FragmentCharacteristicDetail.WriteType = FragmentCharacteristicDetail.WriteType.REMOTE_WRITE
+ private fun initFragmentCharacteristicDetail(
+ bluetoothGattCharacteristic: BluetoothGattCharacteristic,
+ expansionId: Int,
+ service: BluetoothGattService,
+ characteristicExpansion: LinearLayout,
+ displayWriteDialog: Boolean = false,
+ writeType: FragmentCharacteristicDetail.WriteType = FragmentCharacteristicDetail.WriteType.REMOTE_WRITE
): FragmentCharacteristicDetail {
val characteristicDetail = FragmentCharacteristicDetail().apply {
isRemote = this@ServicesFragment.isRemote
@@ -215,17 +230,17 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
}
// show characteristic's expansion and add the fragment to view/edit characteristic detail
parentFragmentManager
- .beginTransaction()
- .add(expansionId, characteristicDetail, CHARACTERISTIC_ADD_FRAGMENT_TRANSACTION_ID)
- .commitNow()
+ .beginTransaction()
+ .add(expansionId, characteristicDetail, CHARACTERISTIC_ADD_FRAGMENT_TRANSACTION_ID)
+ .commitNow()
return characteristicDetail
}
private fun handleOnPropertyClicked(
- property: Property,
- characteristicContainer: CharacteristicItemContainer
+ property: Property,
+ characteristicContainer: CharacteristicItemContainer
) {
if (isMandatorySystemService(characteristicContainer.characteristic.service.uuid)) return
@@ -236,16 +251,17 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
when (property) {
Property.READ -> {
saveCurrentWriteReadFragment(
- bluetoothGattCharacteristic,
- service,
- characteristicExpansion
+ bluetoothGattCharacteristic,
+ service,
+ characteristicExpansion
)
readCharacteristic(bluetoothGattCharacteristic)
}
+
Property.WRITE -> {
val writeType =
- if (this is RemoteServicesFragment) FragmentCharacteristicDetail.WriteType.REMOTE_WRITE
- else FragmentCharacteristicDetail.WriteType.LOCAL_WRITE
+ if (this is RemoteServicesFragment) FragmentCharacteristicDetail.WriteType.REMOTE_WRITE
+ else FragmentCharacteristicDetail.WriteType.LOCAL_WRITE
openWriteDialog(
bluetoothGattCharacteristic,
service,
@@ -253,20 +269,20 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
writeType
)
}
+
Property.NOTIFY -> {
if (this is RemoteServicesFragment) {
saveCurrentWriteReadFragment(
- bluetoothGattCharacteristic,
- service,
- characteristicExpansion
+ bluetoothGattCharacteristic,
+ service,
+ characteristicExpansion
)
toggleNotifications(
bluetoothGattCharacteristic,
characteristicContainer.getPropertyBinding(Property.NOTIFY),
characteristicContainer.getPropertyBinding(Property.INDICATE)
)
- }
- else {
+ } else {
openWriteDialog(
bluetoothGattCharacteristic,
service,
@@ -275,20 +291,20 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
)
}
}
+
Property.INDICATE -> {
if (this is RemoteServicesFragment) {
saveCurrentWriteReadFragment(
- bluetoothGattCharacteristic,
- service,
- characteristicExpansion
+ bluetoothGattCharacteristic,
+ service,
+ characteristicExpansion
)
toggleIndications(
bluetoothGattCharacteristic,
characteristicContainer.getPropertyBinding(Property.INDICATE),
characteristicContainer.getPropertyBinding(Property.NOTIFY)
)
- }
- else {
+ } else {
openWriteDialog(
bluetoothGattCharacteristic,
service,
@@ -297,7 +313,8 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
)
}
}
- else -> { }
+
+ else -> {}
}
}
@@ -327,9 +344,9 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
}
private fun saveCurrentWriteReadFragment(
- characteristic: BluetoothGattCharacteristic,
- service: BluetoothGattService,
- characteristicExpansion: LinearLayout
+ characteristic: BluetoothGattCharacteristic,
+ service: BluetoothGattService,
+ characteristicExpansion: LinearLayout
) {
val id = characteristicExpansion.id
@@ -337,10 +354,10 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
currentWriteReadFragment = characteristicFragments[id]
} else {
currentWriteReadFragment = initFragmentCharacteristicDetail(
- characteristic,
- id,
- service,
- characteristicExpansion
+ characteristic,
+ id,
+ service,
+ characteristicExpansion
)
characteristicFragments[id] = currentWriteReadFragment
}
@@ -353,7 +370,7 @@ abstract class ServicesFragment(private val isRemote: Boolean) : Fragment(R.layo
private fun isMandatorySystemService(uuid: UUID): Boolean {
return (!isRemote &&
(uuid == UUID.fromString(CommonUUID.Service.UUID_GENERIC_ACCESS.toString())
- || uuid == UUID.fromString(CommonUUID.Service.UUID_GENERIC_ATTRIBUTE.toString())))
+ || uuid == UUID.fromString(CommonUUID.Service.UUID_GENERIC_ATTRIBUTE.toString())))
}
override fun onPause() {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/rssi_graph/fragments/RssiGraphFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/rssi_graph/fragments/RssiGraphFragment.kt
index 2d1ee557..1a975ad8 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/rssi_graph/fragments/RssiGraphFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/scan/rssi_graph/fragments/RssiGraphFragment.kt
@@ -25,6 +25,7 @@ import com.siliconlabs.bledemo.features.scan.rssi_graph.utils.GraphDataExporter
import com.siliconlabs.bledemo.features.scan.rssi_graph.views.ChartView
import com.siliconlabs.bledemo.home_screen.base.BluetoothDependent
import com.siliconlabs.bledemo.home_screen.base.LocationDependent
+import com.siliconlabs.bledemo.home_screen.base.NotificationDependent
import java.text.DateFormat
import java.util.*
import java.util.concurrent.ScheduledThreadPoolExecutor
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/activities/MainActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/activities/MainActivity.kt
index d04e208a..3023cb89 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/activities/MainActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/activities/MainActivity.kt
@@ -1,6 +1,7 @@
package com.siliconlabs.bledemo.home_screen.activities
import android.Manifest
+import android.app.NotificationManager
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
@@ -13,25 +14,26 @@ import androidx.navigation.ui.NavigationUI
import com.siliconlabs.bledemo.base.activities.BaseActivity
import com.siliconlabs.bledemo.bluetooth.services.BluetoothService
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.ActivityMainBinding
import com.siliconlabs.bledemo.home_screen.dialogs.PermissionsDialog
import com.siliconlabs.bledemo.home_screen.viewmodels.MainActivityViewModel
import com.siliconlabs.bledemo.home_screen.views.HidableBottomNavigationView
import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.android.synthetic.main.activity_main.*
+
@AndroidEntryPoint
open class MainActivity : BaseActivity(),
BluetoothService.ServicesStateListener
{
-
+ private lateinit var _binding:ActivityMainBinding
private lateinit var viewModel: MainActivityViewModel
private lateinit var binding: BluetoothService.Binding
var bluetoothService: BluetoothService? = null
private set
private val neededPermissions = mutableListOf(
- Manifest.permission.ACCESS_FINE_LOCATION
- )
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ )
@RequiresApi(Build.VERSION_CODES.S)
private val android12Permissions = listOf(
@@ -44,7 +46,9 @@ open class MainActivity : BaseActivity(),
setTheme(R.style.MainAppTheme)
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
+ _binding = ActivityMainBinding.inflate(LayoutInflater.from(this))
+ // setContentView(R.layout.activity_main)
+ setContentView(_binding.root)
supportActionBar?.show()
viewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)
@@ -66,7 +70,8 @@ open class MainActivity : BaseActivity(),
private fun setupMainNavigationListener() {
val navFragment = supportFragmentManager.findFragmentById(R.id.main_fragment) as NavHostFragment
val navController = navFragment.navController
- NavigationUI.setupWithNavController(main_navigation, navController)
+
+ NavigationUI.setupWithNavController(_binding.mainNavigation, navController)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@@ -81,9 +86,9 @@ open class MainActivity : BaseActivity(),
fun toggleMainNavigation(isOn: Boolean) {
if(isOn) {
- main_navigation.show(instant = true)
+ _binding.mainNavigation.show(instant = true)
} else {
- main_navigation.hide(instant = true)
+ _binding.mainNavigation.hide(instant = true)
}
}
@@ -114,6 +119,7 @@ open class MainActivity : BaseActivity(),
bluetoothService?.let {
viewModel.setIsBluetoothOn(it.isBluetoothOn())
viewModel.setIsLocationOn(it.isLocationOn())
+ viewModel.setIsNotificationOn(it.areNotificationOn())
}
observeChanges()
viewModel.setIsSetupFinished(isSetupFinished = true)
@@ -127,7 +133,7 @@ open class MainActivity : BaseActivity(),
}
fun getMainNavigation(): HidableBottomNavigationView? {
- return main_navigation
+ return _binding.mainNavigation
}
override fun onBluetoothStateChanged(isOn: Boolean) {
@@ -138,6 +144,9 @@ open class MainActivity : BaseActivity(),
viewModel.setIsLocationOn(isOn)
}
+ override fun onNotificationStateChanged(isOn: Boolean) {
+ viewModel.setIsNotificationOn(isOn)
+ }
private fun handlePermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/BaseMainMenuFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/BaseMainMenuFragment.kt
index a358c258..a6b4b08a 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/BaseMainMenuFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/BaseMainMenuFragment.kt
@@ -22,7 +22,7 @@ abstract class BaseMainMenuFragment : Fragment(), WithHidableUIElements {
}
}
- private fun restoreHiddenUI() {
+ fun restoreHiddenUI() {
hidableActionButton?.show()
bottomNav.show()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/BaseServiceDependentMainMenuFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/BaseServiceDependentMainMenuFragment.kt
index 02b42f11..5e0493f4 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/BaseServiceDependentMainMenuFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/BaseServiceDependentMainMenuFragment.kt
@@ -17,6 +17,7 @@ abstract class BaseServiceDependentMainMenuFragment : BaseMainMenuFragment() {
protected open val bluetoothDependent: BluetoothDependent? = null
protected open val locationDependent: LocationDependent? = null
protected var activityViewModel: MainActivityViewModel? = null
+ protected open val notificationDependent:NotificationDependent? = null
protected fun toggleBluetoothBar(isOn: Boolean, bar: BluetoothEnableBar) {
bar.visibility = if (isOn) View.GONE else View.VISIBLE
@@ -35,6 +36,8 @@ abstract class BaseServiceDependentMainMenuFragment : BaseMainMenuFragment() {
bar.visibility = if (isPermissionGranted) View.GONE else View.VISIBLE
}
+
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity?.let {
@@ -63,6 +66,12 @@ abstract class BaseServiceDependentMainMenuFragment : BaseMainMenuFragment() {
activityViewModel?.isLocationPermissionGranted?.observe(viewLifecycleOwner, Observer { isGranted ->
locationDependent?.onLocationPermissionStateChanged(isGranted)
})
+ activityViewModel?.isNotificationOn?.observe(viewLifecycleOwner, Observer { isOn ->
+ notificationDependent?.onNotificationStateChanged(isOn)
+ })
+ activityViewModel?.isNotificationPermissionGranted?.observe(viewLifecycleOwner, Observer { areGranted ->
+ notificationDependent?.onNotificationPermissionsStateChanged(areGranted)
+ })
}
}
@@ -74,6 +83,10 @@ abstract class BaseServiceDependentMainMenuFragment : BaseMainMenuFragment() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
bluetoothDependent?.setupBluetoothPermissionsBarButtons()
}
+ notificationDependent?.let {
+ it.setupNotificationBarButtons()
+ it.setupNotificationPermissionBarButtons()
+ }
}
fun showToastLengthShort(message: String) {
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/NotificationDependent.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/NotificationDependent.kt
new file mode 100644
index 00000000..07efb12c
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/NotificationDependent.kt
@@ -0,0 +1,8 @@
+package com.siliconlabs.bledemo.home_screen.base
+
+interface NotificationDependent {
+ fun onNotificationStateChanged(isNotificationOn: Boolean)
+ fun onNotificationPermissionsStateChanged(arePermissionsGranted: Boolean)
+ fun setupNotificationBarButtons()
+ fun setupNotificationPermissionBarButtons()
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/ViewPagerFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/ViewPagerFragment.kt
index fc3da919..8e93d0cc 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/ViewPagerFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/base/ViewPagerFragment.kt
@@ -13,23 +13,28 @@ import com.siliconlabs.bledemo.features.scan.browser.fragments.BrowserFragment
import com.siliconlabs.bledemo.features.scan.active_connections.fragments.ConnectionsFragment
import com.siliconlabs.bledemo.home_screen.viewmodels.ScanFragmentViewModel
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.FragmentViewPagerBinding
import com.siliconlabs.bledemo.home_screen.fragments.ScanFragment
import com.siliconlabs.bledemo.features.scan.rssi_graph.fragments.RssiGraphFragment
-import kotlinx.android.synthetic.main.fragment_view_pager.*
+
class ViewPagerFragment : Fragment() {
private lateinit var viewModel: ScanFragmentViewModel
private var bluetoothService: BluetoothService? = null
+ private lateinit var binding: FragmentViewPagerBinding //fragment_view_pager
override fun onAttach(context: Context) {
super.onAttach(context)
viewModel = getScanFragment().viewModel
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.fragment_view_pager, null)
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentViewPagerBinding.inflate(inflater, container, false)
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -46,11 +51,13 @@ class ViewPagerFragment : Fragment() {
}
private fun initScanPager() {
- scan_view_pager2.apply {
+ binding.scanViewPager2
+ .apply {
adapter = ScanPagerAdapter()
}
- TabLayoutMediator(scan_tab_layout, scan_view_pager2) { tab, position ->
+
+ TabLayoutMediator(binding.scanTabLayout, binding.scanViewPager2) { tab, position ->
tab.text = when (position) {
0 -> getString(R.string.tab_scanner_label)
1 -> getString(R.string.tab_rssi_graph_label)
@@ -62,7 +69,7 @@ class ViewPagerFragment : Fragment() {
private fun setupDataObservers() {
viewModel.numberOfConnectedDevices.observe(viewLifecycleOwner) {
- scan_tab_layout.getTabAt(2)?.text = getString(R.string.tab_connections_label, it)
+ binding.scanTabLayout.getTabAt(2)?.text = getString(R.string.tab_connections_label, it)
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/dialogs/PermissionsDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/dialogs/PermissionsDialog.kt
index 44a2cdb4..3f7ab00b 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/dialogs/PermissionsDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/dialogs/PermissionsDialog.kt
@@ -48,6 +48,10 @@ class PermissionsDialog(
}
if (rationalesToShow.contains(Manifest.permission.ACCESS_FINE_LOCATION)) {
append(getString(R.string.permissions_rationale_location_html))
+ append("
")
+ }
+ if(rationalesToShow.contains(Manifest.permission.POST_NOTIFICATIONS)){
+ append(getString(R.string.permissions_rationale_notification_html))
}
}.toString()
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/dialogs/WarningBarInfoDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/dialogs/WarningBarInfoDialog.kt
index bf923d22..1dd9b11a 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/dialogs/WarningBarInfoDialog.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/dialogs/WarningBarInfoDialog.kt
@@ -8,7 +8,7 @@ import by.kirich1409.viewbindingdelegate.viewBinding
import com.siliconlabs.bledemo.base.fragments.BaseDialogFragment
import com.siliconlabs.bledemo.R
import com.siliconlabs.bledemo.databinding.DialogLocationInfoBinding
-import kotlinx.android.synthetic.main.dialog_location_info.*
+
class WarningBarInfoDialog(private val type: Type) : BaseDialogFragment(
hasCustomWidth = true,
@@ -24,7 +24,7 @@ class WarningBarInfoDialog(private val type: Type) : BaseDialogFragment(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- btn_ok.setOnClickListener { dismiss() }
+ binding.btnOk .setOnClickListener { dismiss() }
initTexts()
}
@@ -33,18 +33,21 @@ class WarningBarInfoDialog(private val type: Type) : BaseDialogFragment(
Type.LOCATION -> R.string.Location_service
Type.LOCATION_PERMISSION -> R.string.location_permission
Type.BLUETOOTH_PERMISSIONS -> R.string.bluetooth_permissions
+ Type.NOTIFICATION_PERMISSION -> R.string.notification_permissions
})
binding.infoDialogDescription.text = getString( when(type) {
Type.LOCATION -> R.string.location_service_info
Type.LOCATION_PERMISSION -> R.string.location_permission_info
Type.BLUETOOTH_PERMISSIONS -> R.string.bluetooth_permissions_info
+ Type.NOTIFICATION_PERMISSION -> R.string.notification_permissions_info
})
}
enum class Type {
LOCATION,
LOCATION_PERMISSION,
- BLUETOOTH_PERMISSIONS
+ BLUETOOTH_PERMISSIONS,
+ NOTIFICATION_PERMISSION
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/ConfigureFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/ConfigureFragment.kt
index 1669debf..bb56c1c9 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/ConfigureFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/ConfigureFragment.kt
@@ -5,17 +5,23 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentContainer
import androidx.viewpager2.adapter.FragmentStateAdapter
+import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.android.material.tabs.TabLayoutMediator
import com.siliconlabs.bledemo.features.configure.advertiser.fragments.AdvertiserFragment
import com.siliconlabs.bledemo.R
+import com.siliconlabs.bledemo.databinding.FragmentConfigureBinding
import com.siliconlabs.bledemo.features.configure.gatt_configurator.fragments.GattConfiguratorFragment
-import kotlinx.android.synthetic.main.fragment_configure.*
+
class ConfigureFragment : Fragment() {
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View {
+ private val binding by viewBinding(FragmentConfigureBinding::bind)
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
return inflater.inflate(R.layout.fragment_configure, null)
}
@@ -23,8 +29,9 @@ class ConfigureFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
activity?.title = getString(R.string.main_navigation_configure_title)
- configure_view_pager2.adapter = ConfigurePagerAdapter()
- TabLayoutMediator(configure_tab_layout, configure_view_pager2) { tab, position ->
+ binding.configureViewPager2 .adapter = ConfigurePagerAdapter()
+
+ TabLayoutMediator( binding.configureTabLayout, binding.configureViewPager2) { tab, position ->
tab.text = when (position) {
0 -> getString(R.string.tab_advertiser_label)
1 -> getString(R.string.tab_gatt_configurator_label)
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 143245be..697c3932 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
@@ -26,10 +26,12 @@ import com.siliconlabs.bledemo.features.demo.wifi_ota_update.AlertErrorDialog
import com.siliconlabs.bledemo.features.demo.wifi_ota_update.WiFiOtaFileManager
import com.siliconlabs.bledemo.features.demo.wifi_ota_update.WiFiOtaFileSelectionDialog
import com.siliconlabs.bledemo.features.demo.wifi_ota_update.WiFiOtaProgressDialog
+import com.siliconlabs.bledemo.features.demo.wifi_throughput.activities.WifiThroughputActivity
import com.siliconlabs.bledemo.home_screen.adapters.DemoAdapter
import com.siliconlabs.bledemo.home_screen.base.BaseServiceDependentMainMenuFragment
import com.siliconlabs.bledemo.home_screen.base.BluetoothDependent
import com.siliconlabs.bledemo.home_screen.base.LocationDependent
+import com.siliconlabs.bledemo.home_screen.base.NotificationDependent
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
@@ -43,6 +45,7 @@ import com.siliconlabs.bledemo.home_screen.menu_items.Motion
import com.siliconlabs.bledemo.home_screen.menu_items.OTADemo
import com.siliconlabs.bledemo.home_screen.menu_items.RangeTest
import com.siliconlabs.bledemo.home_screen.menu_items.Throughput
+import com.siliconlabs.bledemo.home_screen.menu_items.WiFiThroughput
import com.siliconlabs.bledemo.home_screen.menu_items.WifiCommissioning
import java.io.File
import java.io.FileInputStream
@@ -170,6 +173,14 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI
getString(R.string.dev_kit_sensor_917_desc)
)
)
+
+ add(
+ WiFiThroughput(
+ R.drawable.redesign_ic_demo_wifi_throughput,
+ getString(R.string.wifi_title_Throughput),
+ getString(R.string.wifi_main_menu_description_wifi_throughput)
+ )
+ )
}
}
@@ -238,6 +249,7 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI
}
}
+
override fun onDemoItemClicked(demoItem: DemoMenuItem) {
/* if (demoItem.connectType == BluetoothService.GattConnectType.DEV_KIT_SENSOR) {
if (isNetworkAvailable(context)) {
@@ -279,6 +291,26 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI
Toast.LENGTH_SHORT
).show()
}
+ } else if(demoItem.connectType == BluetoothService.GattConnectType.WIFI_THROUGHPUT_TEST){
+ if (isNetworkAvailable(context)) {
+ /*GlobalScope.launch(Dispatchers.Main) {
+ val result = withContext(Dispatchers.IO) {
+ ThroughputUtils.sendEvent()
+ }
+ }*/
+ requireContext().startActivity(
+ Intent(
+ requireContext(),
+ WifiThroughputActivity::class.java
+ )
+ )
+ }else {
+ Toast.makeText(
+ requireContext(),
+ getString(R.string.turn_on_wifi),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
} else {
println("BLE_PROV demoItem:${demoItem.connectType}")
selectDeviceDialog = SelectDeviceDialog.newDialog(demoItem.connectType)
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/TestFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/TestFragment.kt
index 22f97ed8..c1ebfc33 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/TestFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/TestFragment.kt
@@ -11,6 +11,7 @@ import com.siliconlabs.bledemo.features.iop_test.dialogs.AboutIopDialog
import com.siliconlabs.bledemo.home_screen.base.BaseServiceDependentMainMenuFragment
import com.siliconlabs.bledemo.home_screen.base.BluetoothDependent
import com.siliconlabs.bledemo.home_screen.base.LocationDependent
+import com.siliconlabs.bledemo.home_screen.base.NotificationDependent
class TestFragment : BaseServiceDependentMainMenuFragment(), DialogInterface.OnDismissListener {
@@ -107,6 +108,8 @@ class TestFragment : BaseServiceDependentMainMenuFragment(), DialogInterface.OnD
}
}
+
+
override fun onDismiss(dialogInterface: DialogInterface) {
selectDeviceDialog = null
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/ConnectedLighting.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/ConnectedLighting.kt
index ddb86b52..18e74cbb 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/ConnectedLighting.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/ConnectedLighting.kt
@@ -2,7 +2,7 @@ package com.siliconlabs.bledemo.home_screen.menu_items
import com.siliconlabs.bledemo.bluetooth.services.BluetoothService
-class ConnectedLighting(imageResId: Int, title: String, description: String) : DemoMenuItem(imageResId, title, description) {
-
+class ConnectedLighting(imageResId: Int, title: String, description: String) :
+ DemoMenuItem(imageResId, title, description) {
override val connectType = BluetoothService.GattConnectType.LIGHT
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/WiFiThroughput.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/WiFiThroughput.kt
new file mode 100644
index 00000000..0a05b6c4
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/WiFiThroughput.kt
@@ -0,0 +1,8 @@
+package com.siliconlabs.bledemo.home_screen.menu_items
+
+import com.siliconlabs.bledemo.bluetooth.services.BluetoothService
+
+//Sachith
+class WiFiThroughput(imageResId: Int, title: String, description: String) : DemoMenuItem(imageResId, title, description) {
+ override val connectType = BluetoothService.GattConnectType.WIFI_THROUGHPUT_TEST
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/viewmodels/MainActivityViewModel.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/viewmodels/MainActivityViewModel.kt
index 4bafe31f..a1720336 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/viewmodels/MainActivityViewModel.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/viewmodels/MainActivityViewModel.kt
@@ -1,5 +1,6 @@
package com.siliconlabs.bledemo.home_screen.viewmodels
+import androidx.core.content.ContextCompat
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@@ -18,6 +19,12 @@ class MainActivityViewModel : ViewModel() {
private val _isSetupFinished: MutableLiveData = MutableLiveData()
val isSetupFinished: LiveData = _isSetupFinished
+ private val _isNotificationOn: MutableLiveData = MutableLiveData()
+ val isNotificationOn: LiveData = _isNotificationOn
+
+ private val _isNotificationPermissionGranted = MutableLiveData()
+ val isNotificationPermissionGranted: LiveData get() = _isNotificationPermissionGranted
+
fun setIsBluetoothOn(isBluetoothOn: Boolean) {
_isBluetoothOn.postValue(isBluetoothOn)
}
@@ -38,8 +45,19 @@ class MainActivityViewModel : ViewModel() {
_isSetupFinished.postValue(isSetupFinished)
}
+ fun setIsNotificationOn(isNotificationOn: Boolean) {
+ _isNotificationOn.postValue(isNotificationOn)
+ }
+
+ fun setIsNotificationPermissionGranted(isGranted: Boolean){
+ _isNotificationPermissionGranted.postValue(isGranted)
+ }
+
+
fun getIsBluetoothOn(): Boolean = _isBluetoothOn.value ?: false
fun getIsLocationPermissionGranted(): Boolean = _isLocationPermissionGranted.value ?: false
fun getAreBluetoothPermissionsGranted(): Boolean = _areBluetoothPermissionsGranted.value ?: false
fun getIsSetupFinished(): Boolean = _isSetupFinished.value ?: false
+
+
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/viewmodels/ScanFragmentViewModel.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/viewmodels/ScanFragmentViewModel.kt
index bf436c9c..3ad82fe8 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/viewmodels/ScanFragmentViewModel.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/viewmodels/ScanFragmentViewModel.kt
@@ -221,7 +221,10 @@ class ScanFragmentViewModel(private val context: Context) : ScannerViewModel() {
fun toggleViewExpansion(position: Int) {
_filteredDevices.value = _filteredDevices.value?.apply {
- set(position, this[position].copy(isBluetoothInfoExpanded = !this[position].isBluetoothInfoExpanded))
+ println("SICONNECT --this$this")
+ println("SICONNECT --isBluetoothInfoExpanded${this[position].isBluetoothInfoExpanded}")
+ set(position, this[position]
+ .copy(isBluetoothInfoExpanded = !this[position].isBluetoothInfoExpanded))
}
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/views/NoServiceWarningBar.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/views/NoServiceWarningBar.kt
index eef05ebc..613c1af3 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/views/NoServiceWarningBar.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/views/NoServiceWarningBar.kt
@@ -7,10 +7,12 @@ import android.provider.Settings
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
+import androidx.core.content.ContextCompat.startActivity
import androidx.fragment.app.FragmentManager
import com.siliconlabs.bledemo.databinding.NoServiceWarningBarBinding
import com.siliconlabs.bledemo.home_screen.dialogs.WarningBarInfoDialog
+
abstract class NoServiceWarningBar(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
protected val _binding = NoServiceWarningBarBinding.inflate(LayoutInflater.from(context), this, true)
@@ -31,6 +33,13 @@ abstract class NoServiceWarningBar(context: Context, attrs: AttributeSet?) : Lin
.also { context.startActivity(it) }
}
+ protected fun showAppNotificationSettingsScreen() {
+ val intent = Intent()
+ intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
+ intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName())
+ context.startActivity(intent)
+ }
+
protected fun showInfoDialog(type: WarningBarInfoDialog.Type) {
fragmentManager?.let {
WarningBarInfoDialog(type).show(it, "warning_bar_info_dialog")
diff --git a/mobile/src/main/jniLibs/arm64-v8a/libCHIPController.so b/mobile/src/main/jniLibs/arm64-v8a/libCHIPController.so
index c3d04809..01c51ddd 100644
--- a/mobile/src/main/jniLibs/arm64-v8a/libCHIPController.so
+++ b/mobile/src/main/jniLibs/arm64-v8a/libCHIPController.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cd0803645d5ce23a8e310b8961270a2d78566d899945607ad450e8eec8a0d3cf
-size 366663064
+oid sha256:63abfa9662fbfa253121b5c20891d144ccc6b95702e738c187509d2e0bedc92e
+size 90085952
diff --git a/mobile/src/main/jniLibs/arm64-v8a/libc++_shared.so b/mobile/src/main/jniLibs/arm64-v8a/libc++_shared.so
index c7eca00e..e08eb3cd 100644
--- a/mobile/src/main/jniLibs/arm64-v8a/libc++_shared.so
+++ b/mobile/src/main/jniLibs/arm64-v8a/libc++_shared.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f8ccc2038a0774cde288d8e58390236ad2605aad6515dfa0d146647cf40ddbb0
-size 6933952
+oid sha256:9b53fecf513fa050dc28457c7a61d7c31d84f7f72059a2c95053b59eae4d98a8
+size 6937312
diff --git a/mobile/src/main/jniLibs/armeabi-v7a/libCHIPController.so b/mobile/src/main/jniLibs/armeabi-v7a/libCHIPController.so
index 46c2e9dd..77c461c6 100644
--- a/mobile/src/main/jniLibs/armeabi-v7a/libCHIPController.so
+++ b/mobile/src/main/jniLibs/armeabi-v7a/libCHIPController.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cd1667fbd40f7bffa27eb9f181585abd3d5b5bbfa91973bd1638afede9517e4e
-size 352035880
+oid sha256:91221a4eb1b66249182c4b0b6597fabd70bc0e0440f0c7e78c85d2526f97090f
+size 84263980
diff --git a/mobile/src/main/jniLibs/armeabi-v7a/libc++_shared.so b/mobile/src/main/jniLibs/armeabi-v7a/libc++_shared.so
index 3200ef2e..54bdf1a9 100644
--- a/mobile/src/main/jniLibs/armeabi-v7a/libc++_shared.so
+++ b/mobile/src/main/jniLibs/armeabi-v7a/libc++_shared.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:52df819dc40888fb2e736f4cb1e51329afcd9aec6dbcab4fa6a1885a3b84e844
-size 4359916
+oid sha256:22b3ed78887dca77ab2bb39c6633096d5605ab697d1ecd963b3fd628a1c21ade
+size 4364084
diff --git a/mobile/src/main/jniLibs/x86/libCHIPController.so b/mobile/src/main/jniLibs/x86/libCHIPController.so
index 6e8ca513..062bf7d5 100644
--- a/mobile/src/main/jniLibs/x86/libCHIPController.so
+++ b/mobile/src/main/jniLibs/x86/libCHIPController.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:640e3d5b4f1d3667a397b60e910cc368790b3d44356c5267ae660e9a3ecf3efb
-size 354130728
+oid sha256:830563a2f221f135dab22da208e56eed30089de1880c07944bbaff4d0b2ce593
+size 87241828
diff --git a/mobile/src/main/jniLibs/x86/libc++_shared.so b/mobile/src/main/jniLibs/x86/libc++_shared.so
index 8efb21f2..b7e0c8d7 100644
--- a/mobile/src/main/jniLibs/x86/libc++_shared.so
+++ b/mobile/src/main/jniLibs/x86/libc++_shared.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6b57f851b2412a16b88f2ceae8d2ce52c5dc0ea98819b58edf63e1f8abb8c1d0
-size 5645372
+oid sha256:2abfeb5a847ec34d0e9d8c696a8e83072fe3a81e402f4dd3b7a01b374edf59e6
+size 5649592
diff --git a/mobile/src/main/jniLibs/x86_64/libCHIPController.so b/mobile/src/main/jniLibs/x86_64/libCHIPController.so
index c2033628..cea01ecf 100644
--- a/mobile/src/main/jniLibs/x86_64/libCHIPController.so
+++ b/mobile/src/main/jniLibs/x86_64/libCHIPController.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1a8075d839d14ff925639b97ec6e9f64ef6713517b2fb1393a7d99e4636cba9f
-size 360863976
+oid sha256:63f940936f5859ff7204c5ac403b066f091ddfd5a11e5afd3502fe26b3720f6d
+size 87232328
diff --git a/mobile/src/main/jniLibs/x86_64/libc++_shared.so b/mobile/src/main/jniLibs/x86_64/libc++_shared.so
index 0121bab1..39c4ec2c 100644
--- a/mobile/src/main/jniLibs/x86_64/libc++_shared.so
+++ b/mobile/src/main/jniLibs/x86_64/libc++_shared.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:22b0fa946465327af7ad84a32787595d03d2667b53f2304ec72f0a80b34fc393
-size 6716064
+oid sha256:f7dc30aa161b6eb889146ee518ee8a0d1da2d0cc965cd31d31cd39aae11e349a
+size 6719376
diff --git a/mobile/src/main/res/drawable/background_blue_box.xml b/mobile/src/main/res/drawable/background_blue_box.xml
new file mode 100644
index 00000000..580a11d6
--- /dev/null
+++ b/mobile/src/main/res/drawable/background_blue_box.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile/src/main/res/drawable/btn_rounded_blue.xml b/mobile/src/main/res/drawable/btn_rounded_blue.xml
index 56cd2399..b4dbeb5c 100644
--- a/mobile/src/main/res/drawable/btn_rounded_blue.xml
+++ b/mobile/src/main/res/drawable/btn_rounded_blue.xml
@@ -3,7 +3,7 @@
-
-
+
@@ -11,7 +11,7 @@
-
-
+
diff --git a/mobile/src/main/res/drawable/dishwasher_state_on.xml b/mobile/src/main/res/drawable/dishwasher_state_on.xml
new file mode 100644
index 00000000..13f96678
--- /dev/null
+++ b/mobile/src/main/res/drawable/dishwasher_state_on.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/ic_dishwasher_icon_stateoff.xml b/mobile/src/main/res/drawable/ic_dishwasher_icon_stateoff.xml
new file mode 100644
index 00000000..3e7df041
--- /dev/null
+++ b/mobile/src/main/res/drawable/ic_dishwasher_icon_stateoff.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/ic_dishwasher_icon_stateon.xml b/mobile/src/main/res/drawable/ic_dishwasher_icon_stateon.xml
new file mode 100644
index 00000000..4263d280
--- /dev/null
+++ b/mobile/src/main/res/drawable/ic_dishwasher_icon_stateon.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/ic_electric_dish_washer.xml b/mobile/src/main/res/drawable/ic_electric_dish_washer.xml
new file mode 100644
index 00000000..e21c2286
--- /dev/null
+++ b/mobile/src/main/res/drawable/ic_electric_dish_washer.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/mobile/src/main/res/drawable/matter_dishwasher_list.xml b/mobile/src/main/res/drawable/matter_dishwasher_list.xml
new file mode 100644
index 00000000..41bdb034
--- /dev/null
+++ b/mobile/src/main/res/drawable/matter_dishwasher_list.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/matter_dishwasher_off.xml b/mobile/src/main/res/drawable/matter_dishwasher_off.xml
new file mode 100644
index 00000000..69e651c0
--- /dev/null
+++ b/mobile/src/main/res/drawable/matter_dishwasher_off.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/mobile/src/main/res/drawable/matter_dishwasher_on.xml b/mobile/src/main/res/drawable/matter_dishwasher_on.xml
new file mode 100644
index 00000000..d8da7f39
--- /dev/null
+++ b/mobile/src/main/res/drawable/matter_dishwasher_on.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/mobile/src/main/res/drawable/progress_bar_right_to_left.xml b/mobile/src/main/res/drawable/progress_bar_right_to_left.xml
new file mode 100644
index 00000000..c8b1bfce
--- /dev/null
+++ b/mobile/src/main/res/drawable/progress_bar_right_to_left.xml
@@ -0,0 +1,19 @@
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/redesign_ic_demo_wifi_throughput.xml b/mobile/src/main/res/drawable/redesign_ic_demo_wifi_throughput.xml
new file mode 100644
index 00000000..a165994c
--- /dev/null
+++ b/mobile/src/main/res/drawable/redesign_ic_demo_wifi_throughput.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/w0.png b/mobile/src/main/res/drawable/w0.png
new file mode 100644
index 00000000..af7aea58
Binary files /dev/null and b/mobile/src/main/res/drawable/w0.png differ
diff --git a/mobile/src/main/res/drawable/w1.png b/mobile/src/main/res/drawable/w1.png
new file mode 100644
index 00000000..2b0760a6
Binary files /dev/null and b/mobile/src/main/res/drawable/w1.png differ
diff --git a/mobile/src/main/res/drawable/w10.png b/mobile/src/main/res/drawable/w10.png
new file mode 100644
index 00000000..ff9d8f6b
Binary files /dev/null and b/mobile/src/main/res/drawable/w10.png differ
diff --git a/mobile/src/main/res/drawable/w2.png b/mobile/src/main/res/drawable/w2.png
new file mode 100644
index 00000000..61a81a86
Binary files /dev/null and b/mobile/src/main/res/drawable/w2.png differ
diff --git a/mobile/src/main/res/drawable/w3.png b/mobile/src/main/res/drawable/w3.png
new file mode 100644
index 00000000..cd4a7082
Binary files /dev/null and b/mobile/src/main/res/drawable/w3.png differ
diff --git a/mobile/src/main/res/drawable/w4.png b/mobile/src/main/res/drawable/w4.png
new file mode 100644
index 00000000..a7ea9c9b
Binary files /dev/null and b/mobile/src/main/res/drawable/w4.png differ
diff --git a/mobile/src/main/res/drawable/w5.png b/mobile/src/main/res/drawable/w5.png
new file mode 100644
index 00000000..6069171b
Binary files /dev/null and b/mobile/src/main/res/drawable/w5.png differ
diff --git a/mobile/src/main/res/drawable/w6.png b/mobile/src/main/res/drawable/w6.png
new file mode 100644
index 00000000..6bcb94c1
Binary files /dev/null and b/mobile/src/main/res/drawable/w6.png differ
diff --git a/mobile/src/main/res/drawable/w7.png b/mobile/src/main/res/drawable/w7.png
new file mode 100644
index 00000000..1d640a8b
Binary files /dev/null and b/mobile/src/main/res/drawable/w7.png differ
diff --git a/mobile/src/main/res/drawable/w8.png b/mobile/src/main/res/drawable/w8.png
new file mode 100644
index 00000000..798a763f
Binary files /dev/null and b/mobile/src/main/res/drawable/w8.png differ
diff --git a/mobile/src/main/res/drawable/w9.png b/mobile/src/main/res/drawable/w9.png
new file mode 100644
index 00000000..75df6b18
Binary files /dev/null and b/mobile/src/main/res/drawable/w9.png differ
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
index 38e22c19..4543db08 100644
--- 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
@@ -1,8 +1,8 @@
@@ -32,27 +32,64 @@
-
+ app:layout_constraintTop_toTopOf="@+id/env_grid_place">
-
+ android:gravity="center"
+ android:padding="@dimen/adapter_item_padding"
+ android:text="@string/matter_scanner_adapter_empty_list_title"
+ android:textColor="@color/adapter_item_title_color"
+ android:textSize="@dimen/text_size_L" />
+
+
+
+
+
+
+
+
-
+
-
+
\ No newline at end of file
diff --git a/mobile/src/main/res/layout/activity_advertiser_config.xml b/mobile/src/main/res/layout/activity_advertiser_config.xml
index 842467ef..6df2e34c 100644
--- a/mobile/src/main/res/layout/activity_advertiser_config.xml
+++ b/mobile/src/main/res/layout/activity_advertiser_config.xml
@@ -29,13 +29,21 @@
android:orientation="vertical"
android:padding="16dp">
-
+
-
+
-
+
-
+
diff --git a/mobile/src/main/res/layout/activity_environment.xml b/mobile/src/main/res/layout/activity_environment.xml
index 9077d44a..53a392ce 100644
--- a/mobile/src/main/res/layout/activity_environment.xml
+++ b/mobile/src/main/res/layout/activity_environment.xml
@@ -5,9 +5,8 @@
+ app:titleTextColor="#ffff" />
diff --git a/mobile/src/main/res/layout/activity_motion.xml b/mobile/src/main/res/layout/activity_motion.xml
index 03f93cd9..ca94ff90 100644
--- a/mobile/src/main/res/layout/activity_motion.xml
+++ b/mobile/src/main/res/layout/activity_motion.xml
@@ -16,6 +16,7 @@
android:paddingRight="@dimen/iodemo_margin" />
+
+
+
+
\ No newline at end of file
diff --git a/mobile/src/main/res/layout/adapter_advertiser.xml b/mobile/src/main/res/layout/adapter_advertiser.xml
index 371b6f68..3767687b 100644
--- a/mobile/src/main/res/layout/adapter_advertiser.xml
+++ b/mobile/src/main/res/layout/adapter_advertiser.xml
@@ -260,8 +260,8 @@
diff --git a/mobile/src/main/res/layout/adapter_gatt_server.xml b/mobile/src/main/res/layout/adapter_gatt_server.xml
index d59d3205..e2d183a1 100644
--- a/mobile/src/main/res/layout/adapter_gatt_server.xml
+++ b/mobile/src/main/res/layout/adapter_gatt_server.xml
@@ -138,8 +138,8 @@
diff --git a/mobile/src/main/res/layout/advertiser_config_name.xml b/mobile/src/main/res/layout/advertiser_config_name.xml
index bceac55c..fa5b7ade 100644
--- a/mobile/src/main/res/layout/advertiser_config_name.xml
+++ b/mobile/src/main/res/layout/advertiser_config_name.xml
@@ -10,6 +10,7 @@
android:paddingTop="16dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:textSize="@dimen/text_size_SM" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/layout/dialog_network_selection_matter.xml b/mobile/src/main/res/layout/dialog_network_selection_matter.xml
index f71e543a..001c954f 100644
--- a/mobile/src/main/res/layout/dialog_network_selection_matter.xml
+++ b/mobile/src/main/res/layout/dialog_network_selection_matter.xml
@@ -15,7 +15,9 @@
android:layout_gravity="center"
android:gravity="center"
android:layout_marginTop="7dp"
+ android:textColor="@color/silabs_primary_text"
android:text="@string/matter_network_selection_alert_title"
+ android:fontFamily="sans-serif-black"
android:textSize="@dimen/text_size_ML"
android:textStyle="bold" />
@@ -26,8 +28,10 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
+ android:textStyle="bold"
+ android:fontFamily="sans-serif-black"
android:text="@string/matter_select_network_mode_alert_message"
- android:textSize="@dimen/text_size_M" />
+ android:textSize="@dimen/text_size_SM" />
+ android:background="@color/silabs_divider" />
@@ -66,7 +71,7 @@
+ android:background="@color/silabs_divider" />
+ android:background="@color/silabs_divider" />
diff --git a/mobile/src/main/res/layout/fragment_browser.xml b/mobile/src/main/res/layout/fragment_browser.xml
index e8f18654..a78be913 100644
--- a/mobile/src/main/res/layout/fragment_browser.xml
+++ b/mobile/src/main/res/layout/fragment_browser.xml
@@ -41,7 +41,6 @@
android:visibility="gone"
tools:visibility="visible" />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/layout/fragment_matter_window_cover.xml b/mobile/src/main/res/layout/fragment_matter_window_cover.xml
index 6485d8a8..083dd3fa 100644
--- a/mobile/src/main/res/layout/fragment_matter_window_cover.xml
+++ b/mobile/src/main/res/layout/fragment_matter_window_cover.xml
@@ -19,19 +19,36 @@
android:textSize="@dimen/text_size_XL"
android:textStyle="bold" />
-
+ android:layout_marginBottom="@dimen/matter_30dp">
+
+
+
+
+
@@ -39,21 +56,88 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/layout/fragment_otbr_input_dialog.xml b/mobile/src/main/res/layout/fragment_otbr_input_dialog.xml
index c89f26a9..be8e376c 100644
--- a/mobile/src/main/res/layout/fragment_otbr_input_dialog.xml
+++ b/mobile/src/main/res/layout/fragment_otbr_input_dialog.xml
@@ -3,7 +3,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
- android:background="@drawable/matter_popup_background"
+ android:background="@drawable/rounded_dialog_background"
android:gravity="center"
android:orientation="vertical">
@@ -16,6 +16,7 @@
android:gravity="center"
android:text="@string/matter_alert_title"
android:textSize="@dimen/text_size_ML"
+ android:fontFamily="sans-serif-black"
android:textStyle="bold" />
+ android:fontFamily="sans-serif-medium"
+ android:text="@string/matter_otbr_alert_message"
+ android:textSize="@dimen/text_size_SM" />
diff --git a/mobile/src/main/res/layout/fragment_services.xml b/mobile/src/main/res/layout/fragment_services.xml
index 7e80f813..0c06c304 100644
--- a/mobile/src/main/res/layout/fragment_services.xml
+++ b/mobile/src/main/res/layout/fragment_services.xml
@@ -7,7 +7,7 @@
tools:context=".features.scan.browser.fragments.ServicesFragment">
diff --git a/mobile/src/main/res/layout/fragment_wifi_through_put_detail_screen.xml b/mobile/src/main/res/layout/fragment_wifi_through_put_detail_screen.xml
new file mode 100644
index 00000000..ed0bd745
--- /dev/null
+++ b/mobile/src/main/res/layout/fragment_wifi_through_put_detail_screen.xml
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile/src/main/res/layout/matter_scanned_list_item.xml b/mobile/src/main/res/layout/matter_scanned_list_item.xml
index 50fa2721..e73fe7ad 100644
--- a/mobile/src/main/res/layout/matter_scanned_list_item.xml
+++ b/mobile/src/main/res/layout/matter_scanned_list_item.xml
@@ -1,46 +1,49 @@
-
+
+ android:layout_width="@dimen/matter_90dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:gravity="center_vertical">
+
+
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|center_vertical"
+ android:padding="@dimen/matter_5dp">
+ android:layout_gravity="center"
+ android:orientation="horizontal">
-
-
-
-
-
\ No newline at end of file
+
diff --git a/mobile/src/main/res/layout/sensor_demo_grid_item.xml b/mobile/src/main/res/layout/sensor_demo_grid_item.xml
index 289d57e8..741a3dd8 100644
--- a/mobile/src/main/res/layout/sensor_demo_grid_item.xml
+++ b/mobile/src/main/res/layout/sensor_demo_grid_item.xml
@@ -8,8 +8,8 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile/src/main/res/raw/keystore.p12 b/mobile/src/main/res/raw/keystore.p12
new file mode 100644
index 00000000..a785cfc9
Binary files /dev/null and b/mobile/src/main/res/raw/keystore.p12 differ
diff --git a/mobile/src/main/res/values/dimens.xml b/mobile/src/main/res/values/dimens.xml
index 1dce9ee6..0939c5aa 100644
--- a/mobile/src/main/res/values/dimens.xml
+++ b/mobile/src/main/res/values/dimens.xml
@@ -316,8 +316,10 @@
36dp
38dp
40dp
+ 45dp
50dp
90dp
+ 100dp
150dp
200dp
250dp
@@ -331,4 +333,7 @@
240dp
-40dp
40dp
+
+ 118dp
+ 118dp
diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml
index bed9bba5..7fc84251 100644
--- a/mobile/src/main/res/values/strings.xml
+++ b/mobile/src/main/res/values/strings.xml
@@ -102,7 +102,10 @@
Info
Enable
Location disabled
+ Notifications Disabled
Bluetooth permissions denied
+ Notification permissions denied
+ Enable
Location service
On some Android phones you have to enable Location
service in order to scan for Bluetooth Low Energy devices. If you can\'t find any
@@ -112,11 +115,20 @@
you have to grant a permission first. Please keep in mind, that on some Android
devices this service is needed for proper Bluetooth Low Energy device discovery.
Bluetooth permissions
+ Notification permissions
Since Android 12, performing BLE-related operations
(such as scanning, advertising or connecting) requires the user to explicitly grant the
\"Nearby devices\" permission for the app. Please keep in mind that this app relies
heavily on these system features and its capabilities will be severely reduced without them.
+ To ensure you have the best experience with our app, we need your help! Enabling notifications allows us to keep you informed about essential updates related to your nearby Bluetooth devices.
+ \n\n
+ Why Enable Notifications?
\n
+ - Real-Time Alerts: Receive instant notifications about successful connections, disconnections, and any issues that may arise while using Bluetooth devices.
\n
+ - Timely Updates: Get notified when new features or device settings are available, ensuring you’re always using the latest capabilities of your connected devices.
\n
+ - Critical Reminders: Stay aware of important events, such as battery status and maintenance alerts, so you can manage your devices effectively.
+
+ Your privacy is our priority, and we only send notifications that enhance your experience. \n\nPlease allow notifications so you can make the most of your Bluetooth-enabled devices.
Utilize this device as a Bluetooth \n Low
Energy peripheral
View readings from the Health Thermometer service
@@ -601,7 +613,7 @@
Successful import
Created 1 configuration from the XML file
Import with error
- Provided: \"%s\", expected: %s.
+ Provided: \"%s\", expected: %s.
Specifically: \"%s\".
Provided: \"%s\", expected regex pattern: %s.
@@ -809,6 +821,8 @@
crucial for this app to work as intended
\u2022 <b>location</b> - ensures proper
functioning of the bluetooth scanner
+ \u2022 <b>notification</b> - This app requires notification permission to send you important alerts and updates.
+ Please allow notifications so you can stay informed.
Understood
%s
@@ -1097,7 +1111,7 @@
Plug off is in-progress for
Closing window cover is in-progress for
Commissioning completed with result: %1$d
- Commissioning Device
+ Commissioning Device…
Scan QR Code
Hello blank fragment
ON
@@ -1111,7 +1125,7 @@
Switch On Off
Open
Close
- Curtain Open Close
+ Window Covering
Thermostat
Occupancy Sensor
Temperature Sensor
@@ -1124,8 +1138,9 @@
Commissioning
WiFi Configuration
Input network SSID and password that your phone is connected to
- Enter OTBR dataset to control
- Select Network Mode
+ WiFi Not Connected
+ Enter OTBR dataset to connect
+ Select network mode
Light On Off
Wi-Fi
Thread
@@ -1141,23 +1156,24 @@
Occupancy Sensor
Temperature Sensor
Contact Sensor
- Connecting to commissioned device…
+ Connecting to\ncommissioned device…
Please position the camera to point at the QR code
Press and Hold to detect the contact and release the button to undetect the contact
Refresh
Thermostat
Light
Window Cover
+ Dishwasher
Please wait while the work is in progress..
Please press BTN1 button to change sensor value on the Baseboard to test the Temprature Sensor
Matter Devices
- Ok
+ OK
Alert
Do you want to delete Device?
Enter valid QR Code
Press and Hold to detect the occupancy” and release the button to undetect the occupancy
SSID and password required.
- Password must be minimum 8 characters.BT
+ Password must be minimum 8 characters.
Add the device name. This is the name that will be used to reference this device.
Add Device Name
Manual QR code payload ID:
@@ -1168,8 +1184,28 @@
Please enter valid device name
Start Commissioning
QR Code info
-
-
+ Dishwasher
+ QR Code Info
+ START
+ STOP
+ PAUSE
+ Cumulative Energy
+ Please wait…
+ Energy Consumption
+ average per cycle
+ Error while retrieving device information. Please try again.
+ If you cancel, commissioning will stop and it will redirect to the home screen. You need to restart board and try again.
+ 10 min
+ in current cycle
+ Remaining time
+ min
+ RESUME
+ in total
+ average energy per cycle
+ Completed Cycle:
+
+
+
Wi-Fi OTA Demo
Control OTA Firmware update over Wi-Fi.
This is a demonstration how to update the SiWx91x firmware via Wi-Fi by downloading an image from a remote TCP server. Mobile App will act as a TCP server.
@@ -1190,7 +1226,7 @@
Update
Updating Firmware
Alert
- QR Code Info
+
Wi-Fi Sensors
@@ -1211,5 +1247,53 @@
00 dB
Please turn on Wi-Fi in the mobile
Waiting for Response
-
+ Connect your device with Wi-Fi enabled device
+ Tilt
+ Lift
+ Enter Lift % value
+ Enter Tilt % value
+ Enter lift value
+ Please enter value between 1 – 100 to perform Lift Window Curtain.
+ Please enter value between 1 – 100 to perform Tilt Window Curtain.
+ Enter Tilt Value
+ 0.00 kWh
+
+
+ Wi-Fi Throughput
+ Measure Wi-Fi throughput between the mobile device and EFR32
+ TCP Upload
+ UDP Upload
+ TLS Upload
+ TCP Download
+ UDP Download
+ TLS Download
+ Start Server
+ Ensure to flash TCP_TX on the FW and enter the below details to perform TCP throughput.
+ Ensure to flash TCP_RX on the FW and enter the below details to perform TCP throughput.
+ Ensure to flash UDP_TX on the FW and enter the below details to perform UDP throughput.
+ Ensure to flash UDP_RX on the FW and enter the below details to perform UDP throughput.
+ Ensure to flash TLS_TX on the FW and enter the below details to perform TLS throughput.
+ Ensure to flash TLS_RX on the FW and enter the below details to perform TLS throughput.
+ Connecting to server...
+ Interval
+ Transfer
+ Bandwidth
+ Enter Port number
+ Measure Wi-Fi throughput between the mobile device and SiW917
+ TCP Server
+ TCP Client
+ UDP Server
+ UDP Client
+ TLS Server
+ Enter IP Address
+ Please enter valid port number
+ Total bytes received
+ Total bytes sent
+ Throughput achieved
+ Mbps in 30sec successfully
+ Connection couldn\'t be established
+ Ensure right combination of FW is flashed.
+ Navigating back will cause the dishwasher to enter the pause state
+ The Dishwasher energy data will refresh every minute
+
diff --git a/mobile/src/main/res/values/styles.xml b/mobile/src/main/res/values/styles.xml
index 928663c7..0da54eea 100644
--- a/mobile/src/main/res/values/styles.xml
+++ b/mobile/src/main/res/values/styles.xml
@@ -103,7 +103,7 @@
- sans-serif-medium
- @drawable/btn_rounded_blue
- none
- - false
+ - true