diff --git a/README.md b/README.md
index 5cb9b48b..9030c60e 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ EFR Connect includes many demos to test sample apps in the Silicon Labs GSDK qui
- **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.
## Development Features
EFR 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/mobile/build.gradle.kts b/mobile/build.gradle.kts
index 5ddba351..f738a9f0 100644
--- a/mobile/build.gradle.kts
+++ b/mobile/build.gradle.kts
@@ -16,7 +16,6 @@ android {
compileSdk = 33
namespace = "com.siliconlabs.bledemo"
-
defaultConfig {
minSdk = 29
targetSdk = 33
@@ -24,6 +23,8 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
+ packagingOptions { jniLibs { useLegacyPackaging = true } }
+
buildTypes {
release {
isMinifyEnabled = false
@@ -57,8 +58,8 @@ android {
create("blueGecko") {
dimension = versionDim
applicationId = "com.siliconlabs.bledemo"
- versionCode = 48
- versionName = "2.8.2"
+ versionCode = 49
+ versionName = "2.9.0"
}
}
@@ -73,14 +74,7 @@ android {
buildFeatures {
viewBinding = true
-
}
-
-// packagingOptions {
-// jniLibs {
-// useLegacyPackaging = true
-// }
-// }
}
dependencies {
@@ -108,7 +102,8 @@ dependencies {
implementation("io.github.g00fy2.quickie:quickie-bundled:1.7.0")
implementation("com.google.android.flexbox:flexbox:3.0.0")
- // implementation("com.github.PhilJay:MPAndroidChart:v3.0.3")
+ //MPAndroidChart is added as jar library file
+ //implementation("com.github.PhilJay:MPAndroidChart:v3.0.3")
// Navigation
implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
@@ -117,7 +112,6 @@ dependencies {
// Dependency injection
implementation("com.google.dagger:hilt-android:2.45")
- implementation(files("libs/MPAndroidChart-v3.0.1.jar"))
kapt("com.google.dagger:hilt-android-compiler:2.45")
// View binding
@@ -129,7 +123,7 @@ dependencies {
// Parsing
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.opencsv:opencsv:5.6")
- implementation ("androidx.activity:activity:1.6.0-alpha05")
+ implementation("androidx.activity:activity:1.6.0-alpha05")
// Only used for Int.pow() method in a couple of places
implementation("com.google.guava:guava:29.0-android")
@@ -152,5 +146,5 @@ dependencies {
implementation("androidx.camera:camera-lifecycle:1.1.0")
implementation("androidx.camera:camera-view:1.1.0")
implementation("com.google.mlkit:barcode-scanning:17.0.2")
- implementation ("com.daimajia.swipelayout:library:1.2.0@aar")
+ implementation("com.daimajia.swipelayout:library:1.2.0@aar")
}
diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml
index 2b411b12..bae93deb 100644
--- a/mobile/src/main/AndroidManifest.xml
+++ b/mobile/src/main/AndroidManifest.xml
@@ -18,7 +18,10 @@
-
+
+
+
+
@@ -30,8 +33,9 @@
() {
ENVIRONMENT,
IOP_TEST,
ESL_DEMO,
- MATTER_DEMO
+ MATTER_DEMO,
+ WIFI_OTA_UPDATE
}
interface ScanListener {
@@ -280,6 +281,7 @@ class BluetoothService : LocalService() {
addAction(ACTION_GATT_SERVER_REMOVE_NOTIFICATION)
}
registerReceiver(gattServerBroadcastReceiver, filter)
+
}
override fun onDestroy() {
@@ -659,10 +661,13 @@ class BluetoothService : LocalService() {
override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {
super.onMtuChanged(gatt, mtu, status)
- Timber.d("onMtuChanged(): gatt device =${gatt.device.address}, mtu = $mtu")
- addDeviceLog(GattOperationWithParameterLog(gatt, GattOperationLog.Type.MTU_CHANGED,
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ Timber.d("onMtuChanged(): gatt device =${gatt.device.address}, mtu = $mtu")
+ addDeviceLog(GattOperationWithParameterLog(gatt, GattOperationLog.Type.MTU_CHANGED,
status, "mtu = $mtu"))
- extraGattCallback?.onMtuChanged(gatt, mtu, status)
+ extraGattCallback?.onMtuChanged(gatt, mtu, status)
+ }
+
}
override fun onPhyUpdate(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) {
@@ -843,7 +848,7 @@ class BluetoothService : LocalService() {
createNotificationChannel()
val notification = Notification.Builder(this, CHANNEL_ID)
- .setSmallIcon(R.mipmap.efr_redesign_launcher)
+ .setSmallIcon(R.mipmap.si_launcher)
.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)))
@@ -869,7 +874,7 @@ class BluetoothService : LocalService() {
private fun buildAction(actionText: String, actionIntent: PendingIntent) : Notification.Action {
return Notification.Action.Builder(
- R.mipmap.efr_redesign_launcher,
+ R.mipmap.si_launcher,
actionText,
actionIntent
).build()
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/GattQueue.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/GattQueue.kt
index 47f03170..8ea08ea5 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/Utils/GattQueue.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/Utils/GattQueue.kt
@@ -3,6 +3,7 @@ package com.siliconlabs.bledemo.utils
import android.annotation.SuppressLint
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
+import android.util.Log
import java.util.*
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
@@ -62,12 +63,13 @@ class GattQueue(private val gatt: BluetoothGatt?) {
private fun processNextCommand() {
var success = false
+ Log.i("GattQueue","processNextCommand")
val command = commands.poll()
if (command?.gatt != null && command.characteristic != null) {
val gatt = command.gatt
val characteristic = command.characteristic
-
+ Log.i("GattQueue","command.type "+command.type)
success = when (command.type) {
GattCommand.Type.READ -> gatt.readCharacteristic(characteristic)
GattCommand.Type.WRITE -> gatt.writeCharacteristic(characteristic)
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 bc73b515..687dba52 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,7 +1,6 @@
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
@@ -65,7 +64,7 @@ class MatterScannedResultAdapter(
- holder.itemView.setOnClickListener {
+ holder.binding.textViewHeader.setOnClickListener {
runBlocking {
if (onClickListener != null) {
onClickListener!!.onClick(position, matterInfo)
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 547468d4..c0293ef7 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/activities/RangeTestActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/activities/RangeTestActivity.kt
@@ -39,6 +39,10 @@ import kotlin.math.abs
@SuppressLint("MissingPermission")
class RangeTestActivity : BaseDemoActivity(), Controller {
+ private var lowerLimit: Int = 0
+ private var upperLimit: Int = 0
+ private var descriptor2906: BluetoothGattDescriptor? = null
+
private var activeDeviceId = 1
private var advertisementHandler: RangeTestAdvertisementHandler? = null
@@ -188,8 +192,8 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
}
})
}.also {
- it.show(supportFragmentManager, "select_device_dialog")
- }
+ it.show(supportFragmentManager, "select_device_dialog")
+ }
} else {
showRangeTestFragment(presenter.getMode())
}
@@ -781,6 +785,10 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
status: Int
) {
super.onCharacteristicRead(gatt, characteristic, status)
+ val descriptorUuid = UUID.fromString("00002906-0000-1000-8000-00805f9b34fb")
+ if (characteristic != null) {
+ descriptor2906 = characteristic.getDescriptor(descriptorUuid)
+ }
if (status != BluetoothGatt.GATT_SUCCESS) {
handleConnectionError()
@@ -794,11 +802,22 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
if (gattCharacteristic != null) {
updatePresenter(gatt, characteristic, gattCharacteristic)
- if (gattCharacteristic === GattCharacteristic.RangeTestTxPower || gattCharacteristic === GattCharacteristic.RangeTestPayload || gattCharacteristic === GattCharacteristic.RangeTestMaSize) {
+ if (gattCharacteristic === GattCharacteristic.RangeTestTxPower
+ || gattCharacteristic === GattCharacteristic.RangeTestPayload
+ || gattCharacteristic === GattCharacteristic.RangeTestMaSize
+ ) {
val descriptors = characteristic.descriptors
if (descriptors.size > 1) {
queueReadDescriptor(gatt, characteristic, descriptors[descriptors.size - 1])
}
+ } else {
+ if (gattCharacteristic === GattCharacteristic.RangeTestChannel) {
+ val descriptors = characteristic.descriptors
+ if (descriptors.size > 1) {
+ descriptor2906?.let { queueReadDescriptor(gatt, characteristic, it) }
+ }
+
+ }
}
}
}
@@ -809,7 +828,22 @@ class RangeTestActivity : BaseDemoActivity(), Controller {
status: Int
) {
super.onDescriptorRead(gatt, descriptor, status)
+ 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)
+ RangeTestValues.setChannelsMinMax(lowerLimit, upperLimit)
+ val gattCharacteristic1 = GattCharacteristic.fromUuid(descriptor.characteristic.uuid)
+ gattCharacteristic1?.let {
+ updatePresenter(gatt, descriptor, it)
+ }
+ }catch (e:Exception)
+ {
+ e.stackTrace
+ }
+ }
if (status != BluetoothGatt.GATT_SUCCESS) {
handleConnectionError()
return
@@ -1213,7 +1247,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/models/RangeTestValues.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/models/RangeTestValues.kt
index d05eb3e7..46b79532 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/models/RangeTestValues.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/models/RangeTestValues.kt
@@ -13,8 +13,8 @@ class RangeTestValues {
var PACKET_COUNT_LOOKUP: List
var ID_LOOKUP: List
- private const val CHANNELS_MIN = 0
- private const val CHANNELS_MAX = 19
+ private var CHANNELS_MIN = 0
+ private var CHANNELS_MAX = 0
private val PACKET_COUNTS = arrayOf(500, 1000, 2500, 5000, 10000, 25000, 50000)
@@ -39,5 +39,20 @@ class RangeTestValues {
ID_LOOKUP = Collections.unmodifiableList(idLookup)
}
+
+ fun setChannelsMinMax(min: Int, max: Int) {
+ CHANNELS_MIN = min
+ CHANNELS_MAX = max
+ updateChannelLookup()
+ }
+
+ private fun updateChannelLookup() {
+ val channelsLookupSize = CHANNELS_MAX - CHANNELS_MIN + 1
+ val channelsLookup: ArrayList = ArrayList(channelsLookupSize)
+ for (i in 0 until channelsLookupSize) {
+ channelsLookup.add(CHANNELS_MIN + i)
+ }
+ CHANNEL_LOOKUP = Collections.unmodifiableList(channelsLookup)
+ }
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/models/ThunderBoardDevice.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/models/ThunderBoardDevice.kt
index b8cc294f..9b6fdee1 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/models/ThunderBoardDevice.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/models/ThunderBoardDevice.kt
@@ -19,8 +19,11 @@ class ThunderBoardDevice(device: BluetoothDevice) {
THUNDERBOARD_MODEL_SENSE -> Type.THUNDERBOARD_SENSE
THUNDERBOARD_MODEL_BLUE_V1,
THUNDERBOARD_MODEL_BLUE_V2 -> Type.THUNDERBOARD_BLUE
+
THUNDERBOARD_MODEL_DEV_KIT_V1,
- THUNDERBOARD_MODEL_DEV_KIT_V2 -> Type.THUNDERBOARD_DEV_KIT
+ THUNDERBOARD_MODEL_DEV_KIT_V2,
+ THUNDERBOARD_MODEL_DEV_KIT_V3 -> Type.THUNDERBOARD_DEV_KIT
+
else -> Type.UNKNOWN
}
@@ -30,9 +33,9 @@ class ThunderBoardDevice(device: BluetoothDevice) {
UNKNOWN(0);
companion object {
- fun fromInt(code: Int) : PowerSource {
+ fun fromInt(code: Int): PowerSource {
for (source in values()) {
- if (source.value == code ) return source
+ if (source.value == code) return source
}
return UNKNOWN
}
@@ -52,6 +55,7 @@ class ThunderBoardDevice(device: BluetoothDevice) {
const val THUNDERBOARD_MODEL_BLUE_V2 = "BRD4184B"
const val THUNDERBOARD_MODEL_DEV_KIT_V1 = "BRD2601A"
const val THUNDERBOARD_MODEL_DEV_KIT_V2 = "BRD2601B"
+ const val THUNDERBOARD_MODEL_DEV_KIT_V3 = "BRD2608A"
}
}
\ 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 6c18dd5a..5d83a02c 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/activities/BlinkyThunderboardActivity.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/activities/BlinkyThunderboardActivity.kt
@@ -34,12 +34,17 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val view = LayoutInflater.from(this).inflate(R.layout.activity_blinky_thunderboard, null, false)
- colorLEDControl = view.findViewById(R.id.color_led_control) // make the view gone (if necessary) before it can be showed
+ val view =
+ LayoutInflater.from(this).inflate(R.layout.activity_blinky_thunderboard, null, false)
+ colorLEDControl =
+ view.findViewById(R.id.color_led_control) // make the view gone (if necessary) before it can be showed
ledsControl = view.findViewById(R.id.leds_control)
val powerSourceIntent = intent.getIntExtra(SelectDeviceDialog.POWER_SOURCE_EXTRA, 0)
val modelNumberIntent = intent.getStringExtra(SelectDeviceDialog.MODEL_TYPE_EXTRA)
- setControlsVisibility(ThunderBoardDevice.PowerSource.fromInt(powerSourceIntent), modelNumberIntent)
+ setControlsVisibility(
+ ThunderBoardDevice.PowerSource.fromInt(powerSourceIntent),
+ modelNumberIntent
+ )
mainSection?.addView(view)
@@ -77,14 +82,17 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
viewModel.button0.observe(this, Observer { switch_0.setChecked(it) })
viewModel.button1.observe(this, Observer { switch_1.setChecked(it) })
viewModel.led0.observe(this, Observer {
- if (it != led_0.isChecked) led_0.isChecked = it })
+ if (it != led_0.isChecked) led_0.isChecked = it
+ })
viewModel.led1.observe(this, Observer {
- if (it != led_1.isChecked) led_1.isChecked = it })
+ if (it != led_1.isChecked) led_1.isChecked = it
+ })
when (modelNumber) {
ThunderBoardDevice.THUNDERBOARD_MODEL_SENSE,
ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V1,
- ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2 -> {
+ ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2,
+ ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3 -> {
viewModel.colorLed.observe(this, Observer {
colorLEDControl.setColorLEDsUI(it)
})
@@ -99,10 +107,10 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
private fun sendColorLedCommand(rgbState: LedRGBState) {
val data = byteArrayOf(
- (if (rgbState.on) viewModel.rgbLedMask.value!! else 0x00).toByte(),
- (rgbState.red and 0xff).toByte(),
- (rgbState.green and 0xff).toByte(),
- (rgbState.blue and 0xff).toByte()
+ (if (rgbState.on) viewModel.rgbLedMask.value!! else 0x00).toByte(),
+ (rgbState.red and 0xff).toByte(),
+ (rgbState.green and 0xff).toByte(),
+ (rgbState.blue and 0xff).toByte()
)
getRgbLedCharacteristic()?.apply {
@@ -111,24 +119,28 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
}
}
- private fun setControlsVisibility(powerSource: ThunderBoardDevice.PowerSource, modelNumber: String?) {
+ private fun setControlsVisibility(
+ powerSource: ThunderBoardDevice.PowerSource,
+ modelNumber: String?
+ ) {
if (modelNumber == ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V1 ||
- modelNumber == ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2) {
+ modelNumber == ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2
+ ) {
ledsControl.visibility = View.GONE
}
if (modelNumber == ThunderBoardDevice.THUNDERBOARD_MODEL_SENSE &&
- powerSource == ThunderBoardDevice.PowerSource.COIN_CELL) {
+ powerSource == ThunderBoardDevice.PowerSource.COIN_CELL
+ ) {
colorLEDControl.visibility = View.GONE
}
}
@SuppressLint("MissingPermission")
private fun initControls() {
- if (statusFragment.viewModel.thunderboardDevice.value?.
- boardType != ThunderBoardDevice.Type.THUNDERBOARD_SENSE &&
- statusFragment.viewModel.thunderboardDevice.value?.
- boardType != ThunderBoardDevice.Type.THUNDERBOARD_DEV_KIT) {
+ if (statusFragment.viewModel.thunderboardDevice.value?.boardType != ThunderBoardDevice.Type.THUNDERBOARD_SENSE &&
+ statusFragment.viewModel.thunderboardDevice.value?.boardType != ThunderBoardDevice.Type.THUNDERBOARD_DEV_KIT
+ ) {
runOnUiThread { colorLEDControl.visibility = View.GONE }
}
@@ -146,30 +158,31 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
gattQueue.clearAllButLast() // prevent from queueing more gatt commands
}
- private fun getDigitalWriteCharacteristic() : BluetoothGattCharacteristic? {
+ private fun getDigitalWriteCharacteristic(): BluetoothGattCharacteristic? {
return gatt?.getService(
- GattService.AutomationIo.number)?.characteristics
- ?.filter { it.uuid == GattCharacteristic.Digital.uuid } // there are two
- ?.first { it.properties and BluetoothGattCharacteristic.PROPERTY_WRITE != 0 }
+ GattService.AutomationIo.number
+ )?.characteristics
+ ?.filter { it.uuid == GattCharacteristic.Digital.uuid } // there are two
+ ?.first { it.properties and BluetoothGattCharacteristic.PROPERTY_WRITE != 0 }
}
- private fun getDigitalNotifyCharacteristic() : BluetoothGattCharacteristic? {
+ private fun getDigitalNotifyCharacteristic(): BluetoothGattCharacteristic? {
return gatt?.getService(
- GattService.AutomationIo.number)?.characteristics
- ?.filter { it.uuid == GattCharacteristic.Digital.uuid } // there are two
- ?.first { it.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0 }
+ GattService.AutomationIo.number
+ )?.characteristics
+ ?.filter { it.uuid == GattCharacteristic.Digital.uuid } // there are two
+ ?.first { it.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0 }
}
- private fun getRgbLedCharacteristic() : BluetoothGattCharacteristic? {
- return gatt?.getService(GattService.UserInterface.number)?.
- getCharacteristic(GattCharacteristic.RgbLeds.uuid)
+ private fun getRgbLedCharacteristic(): BluetoothGattCharacteristic? {
+ return gatt?.getService(GattService.UserInterface.number)
+ ?.getCharacteristic(GattCharacteristic.RgbLeds.uuid)
}
- private fun getRgbLedMaskDescriptor() : BluetoothGattDescriptor? {
- return gatt?.getService(GattService.UserInterface.number)?.
- getCharacteristic(GattCharacteristic.RgbLeds.uuid)?.
- getDescriptor(LED_MASK_DESCRIPTOR)
+ private fun getRgbLedMaskDescriptor(): BluetoothGattDescriptor? {
+ return gatt?.getService(GattService.UserInterface.number)
+ ?.getCharacteristic(GattCharacteristic.RgbLeds.uuid)?.getDescriptor(LED_MASK_DESCRIPTOR)
}
override val gattCallback: TimeoutGattCallback = object : TimeoutGattCallback() {
@@ -187,9 +200,11 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
queueReadingDeviceCharacteristics()
}
- override fun onCharacteristicRead(gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- status: Int) {
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic,
+ status: Int
+ ) {
super.onCharacteristicRead(gatt, characteristic, status)
gattQueue.handleCommandProcessed()
if (status != BluetoothGatt.GATT_SUCCESS) return
@@ -201,7 +216,9 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
GattCharacteristic.ModelNumberString,
GattCharacteristic.BatteryLevel,
GattCharacteristic.PowerSource,
- GattCharacteristic.FirmwareRevision -> statusFragment.handleBaseCharacteristic(characteristic)
+ GattCharacteristic.FirmwareRevision -> statusFragment.handleBaseCharacteristic(
+ characteristic
+ )
GattCharacteristic.RgbLeds -> {
val on = characteristic.getIntValue(gattCharacteristic.format, 0)
@@ -209,21 +226,24 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
val green = characteristic.getIntValue(gattCharacteristic.format, 2)
val blue = characteristic.getIntValue(gattCharacteristic.format, 3)
val ledState = LedRGBState(
- on != null && on != 0,
- red ?: 0,
- green ?: 0,
- blue ?: 0
+ on != null && on != 0,
+ red ?: 0,
+ green ?: 0,
+ blue ?: 0
)
viewModel.colorLed.postValue(ledState)
}
- else -> { }
+
+ else -> {}
}
}
- override fun onCharacteristicWrite(gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- status: Int) {
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic,
+ status: Int
+ ) {
super.onCharacteristicWrite(gatt, characteristic, status)
gattQueue.handleCommandProcessed()
if (status != BluetoothGatt.GATT_SUCCESS) return
@@ -233,54 +253,63 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
when (gattCharacteristic) {
GattCharacteristic.Digital -> {
val led0State =
- (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.LED_0_ON) != 0
+ (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.LED_0_ON) != 0
val led1State =
- (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.LED_1_ON) != 0
+ (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.LED_1_ON) != 0
viewModel.led0.postValue(led0State)
viewModel.led1.postValue(led1State)
}
+
GattCharacteristic.RgbLeds -> {
val on = characteristic.getIntValue(gattCharacteristic.format, 0)
val red = characteristic.getIntValue(gattCharacteristic.format, 1)
val green = characteristic.getIntValue(gattCharacteristic.format, 2)
val blue = characteristic.getIntValue(gattCharacteristic.format, 3)
val ledState = LedRGBState(
- on != null && on != 0,
- red ?: 0,
- green ?: 0,
- blue ?: 0
+ on != null && on != 0,
+ red ?: 0,
+ green ?: 0,
+ blue ?: 0
)
viewModel.colorLed.postValue(ledState)
}
+
else -> {
}
}
}
- override fun onCharacteristicChanged(gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic) {
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic
+ ) {
super.onCharacteristicChanged(gatt, characteristic)
val gattCharacteristic = GattCharacteristic.fromUuid(characteristic.uuid)
when (gattCharacteristic) {
GattCharacteristic.BatteryLevel,
- GattCharacteristic.PowerSource -> statusFragment.handleBaseCharacteristic(characteristic)
+ GattCharacteristic.PowerSource -> statusFragment.handleBaseCharacteristic(
+ characteristic
+ )
GattCharacteristic.Digital -> {
val button0State =
- (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.BUTTON_0_ON) != 0
+ (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.BUTTON_0_ON) != 0
val button1State =
- (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.BUTTON_1_ON) != 0
+ (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.BUTTON_1_ON) != 0
viewModel.button0.postValue(button0State)
viewModel.button1.postValue(button1State)
}
- else -> { }
+
+ else -> {}
}
}
- override fun onDescriptorRead(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?,
- status: Int) {
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?,
+ status: Int
+ ) {
super.onDescriptorRead(gatt, descriptor, status)
if (descriptor?.uuid == LED_MASK_DESCRIPTOR) {
@@ -289,20 +318,23 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen
}
- override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor,
- status: Int) {
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor,
+ status: Int
+ ) {
super.onDescriptorWrite(gatt, descriptor, status)
gattQueue.handleCommandProcessed()
if (status != BluetoothGatt.GATT_SUCCESS) return
when (descriptor.characteristic.uuid) {
GattCharacteristic.BatteryLevel.uuid -> initControls()
- else -> { }
+ else -> {}
}
}
}
companion object {
- private val LED_MASK_DESCRIPTOR: UUID? = UUID.fromString("1c694489-8825-45cc-8720-28b54b1fbf00")
+ private val LED_MASK_DESCRIPTOR: UUID? =
+ UUID.fromString("1c694489-8825-45cc-8720-28b54b1fbf00")
}
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/adapters/GdxAdapter.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/adapters/GdxAdapter.kt
index 2ee2518b..9b89b0ec 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/adapters/GdxAdapter.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/adapters/GdxAdapter.kt
@@ -263,7 +263,8 @@ class GdxAdapter(private val backgroundColor: Int, modelType: String?) :
ThunderBoardDevice.THUNDERBOARD_MODEL_BLUE_V2 -> this.modelType = ModelType.BLUE
ThunderBoardDevice.THUNDERBOARD_MODEL_SENSE,
ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V1,
- ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2 -> this.modelType = ModelType.SENSE
+ ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2,
+ ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3 -> this.modelType = ModelType.SENSE
else -> this.modelType = ModelType.SENSE
}
}
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
new file mode 100644
index 00000000..49e69cb6
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/AlertErrorDialog.kt
@@ -0,0 +1,40 @@
+package com.siliconlabs.bledemo.features.demo.wifi_ota_update
+
+import android.content.DialogInterface
+import android.os.Bundle
+import android.view.LayoutInflater
+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.*
+
+class AlertErrorDialog(
+ private val otaErrorCallback: OtaErrorCallback
+) : BaseDialogFragment(
+ hasCustomWidth = true,
+ isCanceledOnTouchOutside = false
+) {
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.dialog_alert_error, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ btn_ok.setOnClickListener {
+ dismiss()
+ otaErrorCallback.onDismiss()
+ }
+ }
+
+ override fun onDismiss(dialog: DialogInterface) {
+ super.onDismiss(dialog)
+ otaErrorCallback.onDismiss()
+ }
+
+ interface OtaErrorCallback {
+ fun onDismiss()
+ }
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaFileManager.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaFileManager.kt
new file mode 100644
index 00000000..5b5b7424
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaFileManager.kt
@@ -0,0 +1,53 @@
+package com.siliconlabs.bledemo.features.demo.wifi_ota_update
+
+import android.content.Context
+import android.net.Uri
+import android.provider.OpenableColumns
+import android.widget.Toast
+import com.siliconlabs.bledemo.R
+import java.util.*
+
+class WiFiOtaFileManager(private val context: Context) {
+
+ var otaFilename: String? = null
+ var otaFile: ByteArray? = null
+
+ fun hasCorrectFileExtensionRPS(): Boolean {
+ return otaFilename?.toUpperCase(Locale.ROOT)?.contains(".RPS")!!
+ }
+
+ fun readFilename(uri: Uri) {
+ var result: String? = null
+ if (uri.scheme == "content") {
+ val cursor = context.contentResolver.query(uri, null, null, null, null)
+ cursor?.use { c ->
+ if (c.moveToFirst()) {
+ result = c.getString(c.getColumnIndex(OpenableColumns.DISPLAY_NAME))
+ }
+ c.close()
+ }
+ }
+ if (result == null) {
+ result = uri.path
+ val cut = result?.lastIndexOf('/')
+ if (cut != -1) {
+ result = result?.substring(cut!! + 1)
+ }
+ }
+ otaFilename = result
+ }
+
+ fun readFile(uri: Uri) {
+ context.contentResolver.openInputStream(uri)?.let {
+ otaFile = ByteArray(it.available())
+ it.read(otaFile)
+ } ?: Toast.makeText(context, context.getString(R.string.problem_while_preparing_the_file),
+ Toast.LENGTH_LONG).show()
+ }
+
+ enum class UploadMode {
+ AUTO,
+ USER
+ }
+
+}
\ No newline at end of file
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
new file mode 100644
index 00000000..648b5f07
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaFileSelectionDialog.kt
@@ -0,0 +1,77 @@
+package com.siliconlabs.bledemo.features.demo.wifi_ota_update
+
+import android.content.DialogInterface
+import android.os.Bundle
+import android.view.LayoutInflater
+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
+) {
+
+ private lateinit var _binding: DialogWifiOtaFileUpdateBinding
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ _binding = DialogWifiOtaFileUpdateBinding.inflate(inflater)
+ _binding.wifiIpAddress.text = ipAddress
+ return _binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupUiListeners()
+ ota_cancel.setOnClickListener {
+ dismiss()
+ cancelCallback.onDismiss()
+ }
+ }
+
+ fun setupUiListeners() {
+ _binding.apply {
+ selectAppFileBtn.setOnClickListener { listener.onSelectFileButtonClicked() }
+ otaCancel.setOnClickListener { listener.onCancelButtonClicked() }
+ otaProceed.setOnClickListener { listener.onOtaButtonClicked() }
+ }
+ }
+
+ override fun onDismiss(dialog: DialogInterface) {
+ super.onDismiss(dialog)
+ cancelCallback.onDismiss()
+ }
+
+ fun checkPortNumberValid(): Boolean {
+ return _binding.portId.text.length >= 4
+ }
+ fun changeFileName(newName: String?) {
+ _binding.selectAppFileBtn.text = newName
+ }
+
+ fun enableUploadButton() {
+ _binding.otaProceed.isEnabled = true
+ }
+
+ fun disableUploadButton() {
+ _binding.otaProceed.isEnabled = false
+ }
+
+ fun getPortId() : String {
+ return _binding.portId.text.toString()
+ }
+
+ interface FileSelectionListener {
+ fun onSelectFileButtonClicked()
+ fun onOtaButtonClicked()
+ fun onCancelButtonClicked()
+ }
+
+ interface CancelCallback {
+ fun onDismiss()
+ }
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaProgressDialog.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaProgressDialog.kt
new file mode 100644
index 00000000..03ea0677
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_ota_update/WiFiOtaProgressDialog.kt
@@ -0,0 +1,65 @@
+package com.siliconlabs.bledemo.features.demo.wifi_ota_update
+
+import android.app.Dialog
+import android.content.Context
+import android.view.View
+import android.widget.*
+import com.siliconlabs.bledemo.R
+
+class WiFiOtaProgressDialog(context: Context) : Dialog(context) {
+
+ var progressBar: ProgressBar
+ var dataRate: TextView
+ var dataSize: TextView
+ var filename: TextView
+ var steps: TextView
+ var chrono: Chronometer
+ var btnOtaEnd: Button
+ var btnCancel: Button
+ var sizename: TextView
+ var uploadImage: ProgressBar
+ var firmwareStatus: TextView
+ var wifiIpAddress: TextView
+ var wifiPort: TextView
+
+
+ init {
+ setContentView(R.layout.dialog_wifi_ota_progress)
+ window?.apply {
+ setLayout(
+ (context.resources.displayMetrics.widthPixels * 0.8f).toInt(),
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ )
+ window?.setBackgroundDrawableResource(android.R.color.transparent)
+ }
+
+ progressBar = findViewById(R.id.ota_progress_bar)
+ dataRate = findViewById(R.id.data_rate)
+ dataSize = findViewById(R.id.ota_progress_percent)
+ filename = findViewById(R.id.file_name)
+ steps = findViewById(R.id.ota_number_of_steps)
+ chrono = findViewById(R.id.ota_chronometer)
+ btnOtaEnd = findViewById(R.id.otabutton)
+ btnCancel = findViewById(R.id.cancel)
+ sizename = findViewById(R.id.file_size)
+ uploadImage = findViewById(R.id.connecting_spinner)
+ firmwareStatus = findViewById(R.id.text_firmware_status)
+ wifiIpAddress = findViewById(R.id.wifi_ip_address)
+ wifiPort = findViewById(R.id.wifi_port)
+ }
+
+ override fun show() {
+ super.show()
+ setCanceledOnTouchOutside(false)
+ }
+
+ fun setProgressInfo(fileName: String?, fileSize: Int?, ipAddress: String?, port: String?) {
+ filename.text = fileName
+ steps.text = context.getString(R.string.iop_test_label_1_of_1)
+ sizename.text = context.getString(R.string.iop_test_n_bytes, fileSize)
+ uploadImage.visibility = View.VISIBLE
+ wifiIpAddress.text = ipAddress
+ wifiPort.text = port
+ }
+
+}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/activities/IOPTestActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/activities/IOPTestActivity.kt
index 5f307038..76c8b342 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
@@ -94,14 +94,18 @@ class IOPTestActivity : AppCompatActivity() {
private var mIndexRunning = -1
private var countReTest = 0
private var iopPhase3IndexStartChildrenTest = -1
-
+ private var iopPhase3BondingStep = 2
+ private var iopPhase3ExtraDescriptor: BluetoothGattDescriptor? = null
+ private var read_CCCD_value = ByteArray(1)
+ var isCCCDPass = true
private var testParametersService: BluetoothGattService? = null
private var characteristicIOPPhase3Control: BluetoothGattCharacteristic? = null
private var characteristicIOPPhase3Throughput: BluetoothGattCharacteristic? = null
private var characteristicIOPPhase3ClientSupportedFeatures: BluetoothGattCharacteristic? = null
private var characteristicIOPPhase3DatabaseHash: BluetoothGattCharacteristic? = null
private var characteristicIOPPhase3IOPTestCaching: BluetoothGattCharacteristic? = null
- private var characteristicIOPPhase3IOPTestServiceChangedIndication: BluetoothGattCharacteristic? = null
+ private var characteristicIOPPhase3IOPTestServiceChangedIndication: BluetoothGattCharacteristic? =
+ null
private var characteristicIOPPhase3ServiceChanged: BluetoothGattCharacteristic? = null
private var characteristicIOPPhase3DeviceName: BluetoothGattCharacteristic? = null
@@ -113,7 +117,8 @@ class IOPTestActivity : AppCompatActivity() {
private var mBluetoothEnableDialog: Dialog? = null
private val mListCharacteristics: MutableList = ArrayList()
- private val characteristicsPhase3Security: MutableList = ArrayList()
+ private val characteristicsPhase3Security: MutableList =
+ ArrayList()
private var isDisabled = false
private val mtuValue = 255
@@ -166,13 +171,17 @@ class IOPTestActivity : AppCompatActivity() {
override fun onReceive(context: Context, intent: Intent) {
val state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1)
val prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1)
- val msg = "Bond state change: state " + printBondState(state) + ", previous state " + printBondState(prevState)
+ val msg =
+ "Bond state change: state " + printBondState(state) + ", previous state " + printBondState(
+ prevState
+ )
Log.d(TAG, msg)
if (state == BluetoothDevice.BOND_BONDED && prevState == BluetoothDevice.BOND_BONDING) {
handler?.postDelayed({
if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_SECURITY].getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING
- /* || getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING]
- .getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING*/) {
+ || getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_LE_PRIVACY].getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING
+ /* || getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING]
+ .getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING*/) {
if (mBluetoothGatt != null) {
mListCharacteristics.clear()
characteristicsPhase3Security.clear()
@@ -188,7 +197,11 @@ class IOPTestActivity : AppCompatActivity() {
}
}, 1600)
} else if (state == BluetoothDevice.BOND_BONDING) {
- Toast.makeText(this@IOPTestActivity, R.string.iop_test_toast_bonding, Toast.LENGTH_LONG).show()
+ Toast.makeText(
+ this@IOPTestActivity,
+ R.string.iop_test_toast_bonding,
+ Toast.LENGTH_LONG
+ ).show()
}
}
@@ -210,28 +223,36 @@ class IOPTestActivity : AppCompatActivity() {
private fun printVariant(variant: Int): String {
if (variant == BluetoothDevice.PAIRING_VARIANT_PIN) {
- Toast.makeText(this@IOPTestActivity, R.string.iop_test_toast_press_passkey, Toast.LENGTH_LONG).show()
+ Toast.makeText(
+ this@IOPTestActivity,
+ R.string.iop_test_toast_press_passkey,
+ Toast.LENGTH_LONG
+ ).show()
return "PAIRING_VARIANT_PIN"
}
return variant.toString()
}
}
- private val bluetoothAdapterStateChangeListener: BroadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- val action = intent.action
- val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
- if (action == BluetoothAdapter.ACTION_STATE_CHANGED) {
- Log.d(TAG, "BluetoothAdapter.ACTION_STATE_CHANGED mIndexRunning: $mIndexRunning,state: $state")
- when (state) {
- BluetoothAdapter.STATE_OFF -> {
- disconnectGatt(mBluetoothGatt)
- handler?.removeCallbacksAndMessages(null)
- finish()
+ private val bluetoothAdapterStateChangeListener: BroadcastReceiver =
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val action = intent.action
+ val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
+ if (action == BluetoothAdapter.ACTION_STATE_CHANGED) {
+ Log.d(
+ TAG,
+ "BluetoothAdapter.ACTION_STATE_CHANGED mIndexRunning: $mIndexRunning,state: $state"
+ )
+ when (state) {
+ BluetoothAdapter.STATE_OFF -> {
+ disconnectGatt(mBluetoothGatt)
+ handler?.removeCallbacksAndMessages(null)
+ finish()
+ }
}
}
}
}
- }
/**
* Update data test failed by item
@@ -243,13 +264,20 @@ class IOPTestActivity : AppCompatActivity() {
scanLeDevice(false)
getSiliconLabsTestInfo().listItemTest[index].setStatusTest(Common.IOP3_TC_STATUS_FAILED)
}
- POSITION_TEST_CONNECTION, POSITION_TEST_DISCOVER_SERVICE, POSITION_TEST_SERVICE -> disconnectGatt(mBluetoothGatt)
+
+ POSITION_TEST_CONNECTION, POSITION_TEST_DISCOVER_SERVICE, POSITION_TEST_SERVICE -> disconnectGatt(
+ mBluetoothGatt
+ )
+
else -> {
}
}
+ Log.d(TAG, "listItemTest.size " + getSiliconLabsTestInfo().listItemTest.size)
+
for (i in index until getSiliconLabsTestInfo().listItemTest.size) {
getSiliconLabsTestInfo().listItemTest[i].setStatusTest(Common.IOP3_TC_STATUS_FAILED)
}
+ Log.d(TAG, "POSITION_TEST_SCANNER " + POSITION_TEST_SCANNER)
if (index >= POSITION_TEST_SCANNER) {
isTestRunning = false
isTestFinished = true
@@ -281,6 +309,7 @@ class IOPTestActivity : AppCompatActivity() {
Log.d(TAG, "scanLeDevice at POSITION_TEST_SCANNER")
scanLeDevice(true)
}
+
POSITION_TEST_CONNECTION -> connectToDevice(mBluetoothDevice)
POSITION_TEST_DISCOVER_SERVICE -> mBluetoothGatt?.requestMtu(247)
POSITION_TEST_SERVICE -> runChildrenTestCase(mIndexStartChildrenTest)
@@ -288,11 +317,19 @@ class IOPTestActivity : AppCompatActivity() {
Log.d(TAG, "POSITION_TEST_IOP3_THROUGHPUT")
iopPhase3RunTestCaseThroughput(1)
}
+
+ POSITION_TEST_IOP3_LE_PRIVACY -> {
+ Log.d(TAG, "POSITION_TEST_IOP3_LE_PRIVACY")
+ iopPhase3RunTestCaseLEPrivacy(1)
+ }
+
POSITION_TEST_IOP3_SECURITY -> {
Log.d(TAG, "POSITION_TEST_IOP3_SECURITY")
iopPhase3IndexStartChildrenTest = 0
iopPhase3RunTestCaseSecurity(iopPhase3IndexStartChildrenTest, 1)
}
+
+
/*
POSITION_TEST_IOP3_CACHING -> {
isServiceChangedIndication = 1
@@ -303,10 +340,12 @@ class IOPTestActivity : AppCompatActivity() {
iopPhase3IndexStartChildrenTest = 0
startOtaTestCase(iopPhase3IndexStartChildrenTest)
}
+
POSITION_TEST_IOP3_OTA_WITHOUT_ACK -> {
iopPhase3IndexStartChildrenTest = 1
startOtaTestCase(iopPhase3IndexStartChildrenTest)
}
+
else -> {
}
}
@@ -325,10 +364,13 @@ class IOPTestActivity : AppCompatActivity() {
POSITION_TEST_SCANNER -> {
itemTestCaseInfo.timeStart = mStartTimeScanner
itemTestCaseInfo.setTimeEnd(System.currentTimeMillis())
- Log.d(TAG, "finishItemTest: scanLeDevice startTime: " + itemTestCaseInfo.getTimeEnd())
+ Log.d(
+ TAG,
+ "finishItemTest: scanLeDevice startTime: " + itemTestCaseInfo.getTimeEnd()
+ )
if (itemTestCaseInfo.getStatusTest() == Common.IOP3_TC_STATUS_FAILED) {
countReTest++
- if (countReTest < 6) {
+ if (countReTest < 7) {
itemTestCaseInfo.setStatusTest(-1)
startItemTest(item)
return
@@ -337,13 +379,17 @@ class IOPTestActivity : AppCompatActivity() {
countReTest = 0
}
}
+
POSITION_TEST_CONNECTION -> {
itemTestCaseInfo.timeStart = mStartTimeConnection
itemTestCaseInfo.setTimeEnd(System.currentTimeMillis())
- Log.d(TAG, "finishItemTest: POSITION_TEST_CONNECTION time " + (System.currentTimeMillis() - mStartTimeConnection))
+ Log.d(
+ TAG,
+ "finishItemTest: POSITION_TEST_CONNECTION time " + (System.currentTimeMillis() - mStartTimeConnection)
+ )
if (itemTestCaseInfo.getStatusTest() == Common.IOP3_TC_STATUS_FAILED) {
countReTest++
- if (countReTest < 6) {
+ if (countReTest < 7) {
if (isConnected) {
isConnected = false
mBluetoothGatt?.disconnect()
@@ -357,31 +403,51 @@ class IOPTestActivity : AppCompatActivity() {
countReTest = 0
}
}
+
POSITION_TEST_DISCOVER_SERVICE -> {
itemTestCaseInfo.timeStart = mStartTimeDiscover
itemTestCaseInfo.setTimeEnd(mEndTimeDiscover)
- Log.d(TAG, "finishItemTest: POSITION_TEST_DISCOVER_SERVICE " + (mEndTimeDiscover - mStartTimeDiscover) + "ms")
+ Log.d(
+ TAG,
+ "finishItemTest: POSITION_TEST_DISCOVER_SERVICE " + (mEndTimeDiscover - mStartTimeDiscover) + "ms"
+ )
countReTest = 0
}
+
POSITION_TEST_SERVICE -> {
getItemTestCaseInfo(POSITION_TEST_SERVICE).checkStatusItemService()
Log.d(TAG, "finishItemTest: POSITION_TEST_SERVICE")
countReTest = 0
}
+
POSITION_TEST_IOP3_THROUGHPUT -> {
val throughputAcceptable = calculateAcceptableThroughput()
itemTestCaseInfo.setThroughputBytePerSec(mByteSpeed, throughputAcceptable)
- Log.d(TAG, "finishItemTest: POSITION_TEST_IOP3_THROUGHPUT mByteSpeed $mByteSpeed throughputAcceptable $throughputAcceptable")
+ Log.d(
+ TAG,
+ "finishItemTest: POSITION_TEST_IOP3_THROUGHPUT mByteSpeed $mByteSpeed throughputAcceptable $throughputAcceptable"
+ )
countReTest = 0
}
+
+ POSITION_TEST_IOP3_LE_PRIVACY -> {
+ getItemTestCaseInfo(POSITION_TEST_IOP3_LE_PRIVACY).checkStatusItemService()
+ Log.d(TAG, "finishItemTest: POSITION_TEST_IOP3_LE_PRIVACY")
+ countReTest = 0
+ isTestRunning = false
+ isTestFinished = true
+ }
+
POSITION_TEST_IOP3_SECURITY -> {
getItemTestCaseInfo(POSITION_TEST_IOP3_SECURITY).checkStatusItemService()
Log.d(TAG, "finishItemTest: POSITION_TEST_IOP3_SECURITY")
countReTest = 0
- isTestRunning = false
- isTestFinished = true
+ // isTestRunning = false
+ // isTestFinished = true
mBluetoothService?.isNotificationEnabled = true
}
+
+
/*
POSITION_TEST_IOP3_CACHING -> {
isTestRunning = false
@@ -392,39 +458,62 @@ class IOPTestActivity : AppCompatActivity() {
else -> {
}
}
- if (item != POSITION_TEST_IOP3_SECURITY && countReTest == 0) {
+ if (item != POSITION_TEST_IOP3_LE_PRIVACY && countReTest == 0) {
startItemTest(item + 1)
}
+ /*if (item != POSITION_TEST_IOP3_SECURITY && countReTest == 0) {
+ startItemTest(item + 1)
+ }*/
+
+
+
runOnUiThread { updateUIFooter(isTestRunning) }
mListener?.updateUi()
}
private fun calculateAcceptableThroughput(): Int {
- val notLegacyFw = getSiliconLabsTestInfo().firmwareVersion.split('.')[0].let { it != "" && it.toInt() >= 6 }
+ val notLegacyFw =
+ getSiliconLabsTestInfo().firmwareVersion.split('.')[0].let { it != "" && it.toInt() >= 6 }
val knownPhy = currentRxPhy in arrayOf(BluetoothDevice.PHY_LE_1M, BluetoothDevice.PHY_LE_2M)
- return if(notLegacyFw && knownPhy) {
+
+
+ return if (notLegacyFw && knownPhy) {
try {
- Log.d(TAG, "finishItemTest: POSITION_TEST_IOP3_THROUGHPUT calculating acceptable throughput (new method)")
+ Log.d(
+ TAG,
+ "finishItemTest: POSITION_TEST_IOP3_THROUGHPUT calculating acceptable throughput (new method)"
+ )
val connectionParameters = getSiliconLabsTestInfo().connectionParameters!!
val pdu = connectionParameters.pdu
- val tPacketMicroseconds: Int = when(currentRxPhy){
+ Log.d(TAG, "pdu : " + pdu)
+ val tPacketMicroseconds: Int = when (currentRxPhy) {
BluetoothDevice.PHY_LE_1M -> (8 * pdu) + 492
else -> (4 * pdu) + 396
}
- val connectionIntervalMs: Double = getSiliconLabsTestInfo().connectionParameters!!.interval
+ val connectionIntervalMs: Double =
+ getSiliconLabsTestInfo().connectionParameters!!.interval
val connectionIntervalMicroseconds = connectionIntervalMs * 1000
val connectionIntervalSeconds = connectionIntervalMs / 1000
+ Log.d(TAG, "connectionIntervalMs " + connectionIntervalMs)
val numPacket = floor(connectionIntervalMicroseconds / tPacketMicroseconds)
val sizeEffective = mtu - 3
val fragmentationCount = ceil(mtu.toFloat() / (pdu - 4))
- val velExpected = numPacket * sizeEffective / fragmentationCount / connectionIntervalSeconds
+ val velExpected =
+ numPacket * sizeEffective / fragmentationCount / connectionIntervalSeconds
(0.5 * velExpected).toInt()
} catch (e: NullPointerException) {
- Log.d(TAG, "finishItemTest: POSITION_TEST_IOP3_THROUGHPUT Failed to calculate acceptable throughput")
+ Log.d(
+ TAG,
+ "finishItemTest: POSITION_TEST_IOP3_THROUGHPUT Failed to calculate acceptable throughput"
+ )
0
}
} else {
- Log.d(TAG, "finishItemTest: POSITION_TEST_IOP3_THROUGHPUT calculating acceptable throughput (legacy method)")
+
+ Log.d(
+ TAG,
+ "finishItemTest: POSITION_TEST_IOP3_THROUGHPUT calculating acceptable throughput (legacy method)"
+ )
(mPDULength) * 4 * 1000 * 65 / 1500
}
}
@@ -438,9 +527,15 @@ class IOPTestActivity : AppCompatActivity() {
/**
* Update data test after listening bluetooth gatt callback
*/
- private fun updateDataTest(characteristic: BluetoothGattCharacteristic?, type: Int, status: Int) {
+ private fun updateDataTest(
+ characteristic: BluetoothGattCharacteristic?,
+ type: Int,
+ status: Int
+ ) {
if (characteristic != null) {
- for (itemChildrenTest: ChildrenItemTestInfo in getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!) {
+ for (itemChildrenTest: ChildrenItemTestInfo in getListChildrenItemTestCase(
+ POSITION_TEST_SERVICE
+ )!!) {
if (itemChildrenTest.characteristic?.uuid.toString() == characteristic.uuid.toString()) {
itemChildrenTest.statusRunTest = 1 // 0 running, 1 finish test
itemChildrenTest.valueMtu = mtu
@@ -456,7 +551,9 @@ class IOPTestActivity : AppCompatActivity() {
itemChildrenTest.setDataAndCompareResult(characteristic)
}
}
- for (itemChildrenTest: ChildrenItemTestInfo in getListChildrenItemTestCase(POSITION_TEST_IOP3_SECURITY)!!) {
+ for (itemChildrenTest: ChildrenItemTestInfo in getListChildrenItemTestCase(
+ POSITION_TEST_IOP3_SECURITY
+ )!!) {
if (itemChildrenTest.characteristic?.uuid.toString() == characteristic.uuid.toString()) {
itemChildrenTest.statusRunTest = 1 // 0 running, 1 finish test
when (type) {
@@ -468,6 +565,9 @@ class IOPTestActivity : AppCompatActivity() {
itemChildrenTest.setDataAndCompareResult(characteristic)
}
}
+
+
+
if (mIndexRunning == POSITION_TEST_IOP3_OTA_ACK || mIndexRunning == POSITION_TEST_IOP3_OTA_WITHOUT_ACK) {
if (!otaProcess) {
testParametersService?.let { readCharacteristic(it.characteristics[0]) }
@@ -477,15 +577,27 @@ class IOPTestActivity : AppCompatActivity() {
} else {
checkIOP3OTA(mIndexRunning, Common.IOP3_TC_STATUS_FAILED)
}
- handler?.postDelayed( {
- finishItemTest(mIndexRunning, getSiliconLabsTestInfo().listItemTest[mIndexRunning])
- }, 100) /* Read testParametersService characteristic before starting next test case. */
+ handler?.postDelayed(
+ {
+ finishItemTest(
+ mIndexRunning,
+ getSiliconLabsTestInfo().listItemTest[mIndexRunning]
+ )
+ },
+ 100
+ ) /* Read testParametersService characteristic before starting next test case. */
}
}
} else if (characteristicIOPPhase3Control?.uuid.toString() == characteristic.uuid.toString()) {
if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_THROUGHPUT].getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING) {
iopPhase3RunTestCaseThroughput(0)
- } /* else if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING]
+ } /*else if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_LE_PRIVACY].getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING) {
+ iopPhase3RunTestCaseLEPrivacy(0)
+ finishItemTest(
+ POSITION_TEST_IOP3_LE_PRIVACY,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_LE_PRIVACY]
+ )
+ }*/ /* else if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING]
.getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING) {
if (isServiceChangedIndication == 0) {
handler?.postDelayed({
@@ -501,7 +613,8 @@ class IOPTestActivity : AppCompatActivity() {
if (isServiceChangedIndication == 1) {
if (characteristicIOPPhase3IOPTestServiceChangedIndication != null) {
if (characteristicIOPPhase3IOPTestServiceChangedIndication?.uuid.toString() == characteristic.uuid.toString()) {
- val itemChildrenTest = getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![isServiceChangedIndication]
+ val itemChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![isServiceChangedIndication]
itemChildrenTest.statusRead = status
itemChildrenTest.statusRunTest = 1
itemChildrenTest.setDataAndCompareResult((itemChildrenTest.characteristic)!!)
@@ -510,15 +623,23 @@ class IOPTestActivity : AppCompatActivity() {
} else {
if (characteristicIOPPhase3DatabaseHash?.uuid.toString() == characteristic.uuid.toString()) {
if (iopPhase3DatabaseHash != null) {
- val itemTestInfo = getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![0]
- if (!itemTestInfo.compareValueCharacteristic(iopPhase3DatabaseHash!!, Converters.getHexValue(characteristic.value))) {
+ val itemTestInfo =
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![0]
+ if (!itemTestInfo.compareValueCharacteristic(
+ iopPhase3DatabaseHash!!,
+ Converters.getHexValue(characteristic.value)
+ )
+ ) {
Log.d(TAG, "iopPhase3DatabaseHash has changed")
mListCharacteristics.clear()
characteristicsPhase3Security.clear()
refreshServices()
}
} else {
- setNotificationForCharacteristic(characteristicIOPPhase3ServiceChanged, Notifications.DISABLED)
+ setNotificationForCharacteristic(
+ characteristicIOPPhase3ServiceChanged,
+ Notifications.DISABLED
+ )
}
iopPhase3DatabaseHash = Converters.getHexValue(characteristic.value)
Log.d(TAG, "characteristicIOPPhase3DatabaseHash: $iopPhase3DatabaseHash")
@@ -526,7 +647,8 @@ class IOPTestActivity : AppCompatActivity() {
readCharacteristic(characteristicIOPPhase3DatabaseHash)
} else if (characteristicIOPPhase3IOPTestCaching != null) {
if (characteristicIOPPhase3IOPTestCaching?.uuid.toString() == characteristic.uuid.toString()) {
- val itemChildrenTest = getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![isServiceChangedIndication]
+ val itemChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![isServiceChangedIndication]
itemChildrenTest.statusRead = status
itemChildrenTest.statusRunTest = 1
itemChildrenTest.setDataAndCompareResult((itemChildrenTest.characteristic)!!)
@@ -534,11 +656,15 @@ class IOPTestActivity : AppCompatActivity() {
if (itemChildrenTest.statusChildrenTest) {
getItemTestCaseInfo(POSITION_TEST_IOP3_CACHING).setStatusTest(Common.IOP3_TC_STATUS_PASS)
}
- finishItemTest(POSITION_TEST_IOP3_CACHING, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING])
+ finishItemTest(
+ POSITION_TEST_IOP3_CACHING,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING]
+ )
}
}
}
}
+
}
}
@@ -565,7 +691,12 @@ class IOPTestActivity : AppCompatActivity() {
mBluetoothBinding = object : BluetoothService.Binding(applicationContext) {
override fun onBound(service: BluetoothService?) {
service?.isNotificationEnabled = false
- mBluetoothGatt = mBluetoothDevice?.connectGatt(applicationContext, false, gattCallback, BluetoothDevice.TRANSPORT_LE)
+ mBluetoothGatt = mBluetoothDevice?.connectGatt(
+ applicationContext,
+ false,
+ gattCallback,
+ BluetoothDevice.TRANSPORT_LE
+ )
}
}
mBluetoothBinding?.bind()
@@ -623,6 +754,38 @@ class IOPTestActivity : AppCompatActivity() {
}, 1000)
}
+ private var onConnectionSuccess: (() -> Unit)? = null
+ private var onConnectionFailure: (() -> Unit)? = null
+
+
+ private fun connectToDevice(
+ bluetoothDevice: BluetoothDevice?,
+ onConnectionSuccess: (() -> Unit)? = null,
+ onConnectionFailure: (() -> Unit)? = null
+ ) {
+ Log.d(TAG, "connectToDevice() with param called with: bluetoothDevice = $bluetoothDevice")
+ mStartTimeConnection = System.currentTimeMillis()
+
+ // Save the callback functions
+ this.onConnectionSuccess = onConnectionSuccess
+ this.onConnectionFailure = onConnectionFailure
+
+ Log.d(TAG, "connectToDevice() with param, postDelayed connectionRunnable")
+ handler?.postDelayed({
+ // Execute the connection logic after the delay
+ mBluetoothBinding = object : BluetoothService.Binding(applicationContext) {
+ override fun onBound(service: BluetoothService?) {
+ mBluetoothService = service
+ service?.isNotificationEnabled = false
+ service?.connectGatt(bluetoothDevice!!, false, gattCallback)
+ mBluetoothGatt = service?.connectedGatt!!
+ }
+ }
+ mBluetoothBinding?.bind()
+ }, 15000) // 15 seconds delay
+ }
+
+
private fun connectToDevice(bluetoothDevice: BluetoothDevice?) {
Log.d(TAG, "connectToDevice() called with: bluetoothDevice = $bluetoothDevice")
mStartTimeConnection = System.currentTimeMillis()
@@ -667,21 +830,41 @@ class IOPTestActivity : AppCompatActivity() {
btn_start_and_stop_test.apply {
text = getString(R.string.button_run_test)
isEnabled = true
- backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this@IOPTestActivity, R.color.silabs_blue))
+ backgroundTintList = ColorStateList.valueOf(
+ ContextCompat.getColor(
+ this@IOPTestActivity,
+ R.color.silabs_blue
+ )
+ )
}
if (isTestFinished) {
shareMenuItem?.isVisible = true
+ mBluetoothDevice?.let { removeBond(it) }
}
} else {
btn_start_and_stop_test?.apply {
text = getString(R.string.button_waiting)
- backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this@IOPTestActivity, R.color.silabs_inactive_light))
+ backgroundTintList = ColorStateList.valueOf(
+ ContextCompat.getColor(
+ this@IOPTestActivity,
+ R.color.silabs_inactive_light
+ )
+ )
isEnabled = false
}
shareMenuItem?.isVisible = false
}
}
+ private fun removeBond(device: BluetoothDevice): Boolean {
+ return try {
+ return device::class.java.getMethod("removeBond").invoke(device) as Boolean
+ } catch (e: Exception) {
+ false
+ }
+ }
+
+
/**
* Show information device test and progress test item
*/
@@ -689,15 +872,21 @@ class IOPTestActivity : AppCompatActivity() {
val siliconlabsTestInfo = getSiliconLabsTestInfo()
runOnUiThread {
if (isInformation || item == POSITION_TEST_CONNECTION) {
- tv_fw_name.text = getString(R.string.iop_test_label_fw_name, siliconlabsTestInfo.fwName)
- tv_device_name.text = getString(R.string.iop_test_label_device_name, siliconlabsTestInfo.phoneName)
+ tv_fw_name.text =
+ getString(R.string.iop_test_label_fw_name, siliconlabsTestInfo.fwName)
+ tv_device_name.text =
+ getString(R.string.iop_test_label_device_name, siliconlabsTestInfo.phoneName)
}
val total = siliconlabsTestInfo.totalTestCase.toString()
if (item == POSITION_TEST_SERVICE) {
testCaseCount = item + mIndexStartChildrenTest + 1
}
Log.d(TAG, "The number of test case $testCaseCount")
- tv_progress.text = getString(R.string.iop_test_label_progress_count_test, testCaseCount.toString(), total)
+ tv_progress.text = getString(
+ R.string.iop_test_label_progress_count_test,
+ testCaseCount.toString(),
+ total
+ )
}
}
@@ -783,7 +972,11 @@ class IOPTestActivity : AppCompatActivity() {
private fun checkIfBluetoothIsSupported() {
if (BluetoothAdapter.getDefaultAdapter() == null) {
- Toast.makeText(this, R.string.iop_test_toast_bluetooth_not_supported, Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ this,
+ R.string.iop_test_toast_bluetooth_not_supported,
+ Toast.LENGTH_SHORT
+ ).show()
finish()
}
}
@@ -802,10 +995,12 @@ class IOPTestActivity : AppCompatActivity() {
saveLogFile()
true
}
+
android.R.id.home -> {
onBackPressed()
true
}
+
else -> false
}
}
@@ -822,9 +1017,19 @@ class IOPTestActivity : AppCompatActivity() {
}
private fun registerBroadcastReceivers() {
- registerReceiver(mBondStateReceiver, IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED))
- registerReceiver(mPairRequestReceiver, IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST))
- registerReceiver(bluetoothAdapterStateChangeListener, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
+ registerReceiver(
+ mBondStateReceiver, IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED),
+ RECEIVER_EXPORTED
+ )
+ registerReceiver(
+ mPairRequestReceiver, IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST),
+ RECEIVER_EXPORTED
+ )
+ registerReceiver(
+ bluetoothAdapterStateChangeListener,
+ IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED),
+ RECEIVER_EXPORTED
+ )
}
private fun handleClickEvents() {
@@ -887,15 +1092,15 @@ class IOPTestActivity : AppCompatActivity() {
*/
private fun showDialogConfirmStopTest() {
AlertDialog.Builder(this)
- .setMessage(getString(R.string.iop_test_message_stop_test))
- .setPositiveButton(getString(R.string.button_ok)) { dialog, _ ->
- dialog.dismiss()
- mBluetoothService?.isNotificationEnabled = true
- disconnectGatt(mBluetoothGatt)
- finish()
- }.setNegativeButton(getString(R.string.button_cancel)) { dialog, _ ->
- dialog.dismiss()
- }.show()
+ .setMessage(getString(R.string.iop_test_message_stop_test))
+ .setPositiveButton(getString(R.string.button_ok)) { dialog, _ ->
+ dialog.dismiss()
+ mBluetoothService?.isNotificationEnabled = true
+ disconnectGatt(mBluetoothGatt)
+ finish()
+ }.setNegativeButton(getString(R.string.button_cancel)) { dialog, _ ->
+ dialog.dismiss()
+ }.show()
}
/**
@@ -916,6 +1121,7 @@ class IOPTestActivity : AppCompatActivity() {
mBluetoothEnableDialog?.show()
}
}
+
GBL_FILE_CHOICE_REQUEST_CODE -> {
intent?.data?.let {
otaFileManager?.readFilename(it)
@@ -924,9 +1130,14 @@ class IOPTestActivity : AppCompatActivity() {
otaFileManager?.readFile(it)
otaFileSelectionDialog?.enableUploadButton()
} else {
- Toast.makeText(this, getString(R.string.incorrect_file), Toast.LENGTH_SHORT).show()
+ Toast.makeText(this, getString(R.string.incorrect_file), Toast.LENGTH_SHORT)
+ .show()
}
- } ?: 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()
}
}
}
@@ -934,7 +1145,10 @@ class IOPTestActivity : AppCompatActivity() {
/**
* Enable indicate by characteristics
*/
- private fun setIndicationProperty(characteristic: BluetoothGattCharacteristic?, indicate: Notifications) {
+ private fun setIndicationProperty(
+ characteristic: BluetoothGattCharacteristic?,
+ indicate: Notifications
+ ) {
setNotificationForCharacteristic(
mBluetoothGatt!!,
characteristic,
@@ -946,7 +1160,10 @@ class IOPTestActivity : AppCompatActivity() {
/**
* Enable notification by characteristics
*/
- private fun setNotificationForCharacteristic(characteristic: BluetoothGattCharacteristic?, notifications: Notifications) {
+ private fun setNotificationForCharacteristic(
+ characteristic: BluetoothGattCharacteristic?,
+ notifications: Notifications
+ ) {
setNotificationForCharacteristic(
mBluetoothGatt!!,
characteristic,
@@ -955,10 +1172,49 @@ class IOPTestActivity : AppCompatActivity() {
)
}
+
+ /**
+ * Write down the value in characteristics and wait for response
+ */
+ private fun writeValueToCharacteristic(
+ characteristic: BluetoothGattCharacteristic?,
+ value: String?,
+ byteValues: ByteArray?,
+ callback: (Boolean) -> Unit // Callback parameter
+ ) {
+ var newValue: ByteArray? = null
+ if (byteValues != null) {
+ newValue = byteValues
+ } else if (!TextUtils.isEmpty(value)) {
+ newValue = Converters.hexToByteArray(value!!)
+ }
+ if (isSetProperty(Common.PropertyType.WRITE, characteristic!!.properties)) {
+ characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
+ } else if (isSetProperty(
+ Common.PropertyType.WRITE_NO_RESPONSE,
+ characteristic.properties
+ )
+ ) {
+ characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
+ }
+ characteristic.value = newValue
+ Log.d(TAG, "writeValueToCharacteristic " + characteristic.uuid.toString())
+
+ // Perform the write operation asynchronously
+ val success = mBluetoothGatt?.writeCharacteristic(characteristic) ?: false
+
+ // Invoke the callback with the write operation result
+ callback(success)
+ }
+
/**
* Write down the value in characteristics
*/
- private fun writeValueToCharacteristic(characteristic: BluetoothGattCharacteristic?, value: String?, byteValues: ByteArray?) {
+ private fun writeValueToCharacteristic(
+ characteristic: BluetoothGattCharacteristic?,
+ value: String?,
+ byteValues: ByteArray?
+ ) {
var newValue: ByteArray? = null
if (byteValues != null) {
newValue = byteValues
@@ -967,13 +1223,23 @@ class IOPTestActivity : AppCompatActivity() {
}
if (isSetProperty(Common.PropertyType.WRITE, characteristic!!.properties)) {
characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
- } else if (isSetProperty(Common.PropertyType.WRITE_NO_RESPONSE, characteristic.properties)) {
+ } else if (isSetProperty(
+ Common.PropertyType.WRITE_NO_RESPONSE,
+ characteristic.properties
+ )
+ ) {
characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
}
characteristic.value = newValue
Log.d(TAG, "writeValueToCharacteristic " + characteristic.uuid.toString())
if (!mBluetoothGatt!!.writeCharacteristic(characteristic)) {
- Log.e(TAG, String.format("ERROR: writeCharacteristic failed for characteristic: %s", characteristic.uuid))
+ Log.e(
+ TAG,
+ String.format(
+ "ERROR: writeCharacteristic failed for characteristic: %s",
+ characteristic.uuid
+ )
+ )
}
}
@@ -1016,15 +1282,18 @@ class IOPTestActivity : AppCompatActivity() {
CommonUUID.Characteristic.IOP_TEST_PHASE3_SERVICE_CHANGED.toString() == item.uuid.toString() -> {
characteristicIOPPhase3ServiceChanged = item
}
+
CommonUUID.Characteristic.IOP_TEST_PHASE3_CLIENT_SUPPORT_FEATURES.toString() == item.uuid.toString() -> {
characteristicIOPPhase3ClientSupportedFeatures = item
}
+
CommonUUID.Characteristic.IOP_TEST_PHASE3_DATABASE_HASH.toString() == item.uuid.toString() -> {
characteristicIOPPhase3DatabaseHash = item
}
}
}
}
+
CommonUUID.Service.UUID_GENERIC_ACCESS.toString() -> {
val gattCharacteristics = gattService.characteristics
for (item: BluetoothGattCharacteristic in gattCharacteristics) {
@@ -1034,10 +1303,12 @@ class IOPTestActivity : AppCompatActivity() {
}
}
}
+
CommonUUID.Service.TEST_PARAMETERS.toString() -> {
count++
testParametersService = gattService
}
+
CommonUUID.Service.UUID_PROPERTIES_SERVICE.toString(),
CommonUUID.Service.UUID_CHARACTERISTICS_SERVICE.toString() -> {
count++
@@ -1046,6 +1317,7 @@ class IOPTestActivity : AppCompatActivity() {
mListCharacteristics.add(item)
}
}
+
CommonUUID.Service.UUID_PHASE3_SERVICE.toString() -> {
Log.d(TAG, "mBluetoothGattServicePhase3 " + gattService.uuid.toString())
val gattCharacteristicsIOPPhase3 = gattService.characteristics
@@ -1055,17 +1327,27 @@ class IOPTestActivity : AppCompatActivity() {
CommonUUID.Characteristic.IOP_TEST_PHASE3_CONTROL.toString() -> {
characteristicIOPPhase3Control = item
}
+
CommonUUID.Characteristic.IOP_TEST_THROUGHPUT.toString() -> {
characteristicIOPPhase3Throughput = item
}
+
CommonUUID.Characteristic.IOP_TEST_GATT_CATCHING.toString() -> {
characteristicIOPPhase3IOPTestCaching = item
- Log.d(TAG, "characteristicIOPPhase3IOPTestCaching " + characteristicIOPPhase3IOPTestCaching?.uuid.toString())
+ Log.d(
+ TAG,
+ "characteristicIOPPhase3IOPTestCaching " + characteristicIOPPhase3IOPTestCaching?.uuid.toString()
+ )
}
+
CommonUUID.Characteristic.IOP_TEST_SERVICE_CHANGED_INDICATION.toString() -> {
characteristicIOPPhase3IOPTestServiceChangedIndication = item
- Log.d(TAG, "characteristicIOPPhase3IOPTestServiceChangedIndication " + characteristicIOPPhase3IOPTestServiceChangedIndication?.uuid.toString())
+ Log.d(
+ TAG,
+ "characteristicIOPPhase3IOPTestServiceChangedIndication " + characteristicIOPPhase3IOPTestServiceChangedIndication?.uuid.toString()
+ )
}
+
CommonUUID.Characteristic.IOP_TEST_SECURITY_PAIRING.toString(),
CommonUUID.Characteristic.IOP_TEST_SECURITY_AUTHENTICATION.toString(),
CommonUUID.Characteristic.IOP_TEST_SECURITY_BONDING.toString() -> {
@@ -1075,14 +1357,27 @@ class IOPTestActivity : AppCompatActivity() {
}
}
}
+
CommonUUID.Service.UUID_BLE_OTA.toString() -> {
val gattCharacteristics = gattService.characteristics
for (gattCharacteristic: BluetoothGattCharacteristic in gattCharacteristics) {
val characteristicUUID = gattCharacteristic.uuid.toString()
- Log.i(TAG, "onServicesDiscovered Characteristic UUID " + characteristicUUID + " - Properties: " + gattCharacteristic.properties)
+ Log.i(
+ TAG,
+ "onServicesDiscovered Characteristic UUID " + characteristicUUID + " - Properties: " + gattCharacteristic.properties
+ )
if (gattCharacteristic.uuid.toString() == ota_control.toString()) {
- if (gattCharacteristics.contains(mBluetoothGatt?.getService(ota_service)?.getCharacteristic(ota_data))) {
- if (!gattServices.contains(mBluetoothGatt?.getService(homekit_service))) {
+ if (gattCharacteristics.contains(
+ mBluetoothGatt?.getService(ota_service)
+ ?.getCharacteristic(ota_data)
+ )
+ ) {
+ if (!gattServices.contains(
+ mBluetoothGatt?.getService(
+ homekit_service
+ )
+ )
+ ) {
Log.i(TAG, "onServicesDiscovered Device in DFU Mode")
mBluetoothGatt?.requestMtu(247)
} else {
@@ -1107,23 +1402,28 @@ class IOPTestActivity : AppCompatActivity() {
}
for (i in getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indices) {
for (j in i until mListCharacteristics.size) {
- getListChildrenItemTestCase(POSITION_TEST_SERVICE)!![i].characteristic = mListCharacteristics[j]
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!![i].characteristic =
+ mListCharacteristics[j]
break
}
}
for (i in getListChildrenItemTestCase(POSITION_TEST_IOP3_SECURITY)!!.indices) {
for (j in i until characteristicsPhase3Security.size) {
- getListChildrenItemTestCase(POSITION_TEST_IOP3_SECURITY)!![i].characteristic = characteristicsPhase3Security[j]
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_SECURITY)!![i].characteristic =
+ characteristicsPhase3Security[j]
break
}
}
+
+
when (mIndexRunning) {
POSITION_TEST_DISCOVER_SERVICE -> {
testParametersService?.let {
handler?.postDelayed({ readCharacteristic(it.characteristics[0]) }, 5000)
}
}
+
POSITION_TEST_IOP3_OTA_WITHOUT_ACK,
POSITION_TEST_IOP3_OTA_ACK -> {
if (!otaProcess) {
@@ -1133,19 +1433,40 @@ class IOPTestActivity : AppCompatActivity() {
}, 5000)
}
}
+
POSITION_TEST_IOP3_THROUGHPUT -> {
mEndThroughputNotification = false
- finishItemTest(POSITION_TEST_IOP3_THROUGHPUT, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_THROUGHPUT])
+ finishItemTest(
+ POSITION_TEST_IOP3_THROUGHPUT,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_THROUGHPUT]
+ )
}
+
+ POSITION_TEST_IOP3_LE_PRIVACY -> {
+ return
+ /* finishItemTest(
+ POSITION_TEST_IOP3_LE_PRIVACY,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_LE_PRIVACY]
+ )*/
+ }
+
POSITION_TEST_IOP3_SECURITY -> {
- iopPhase3RunTestCaseSecurity(iopPhase3IndexStartChildrenTest, 0)
+ if (iopPhase3BondingStep == 2) {
+ iopPhase3RunTestCaseSecurity(iopPhase3IndexStartChildrenTest, 0)
+ } else {
+ iopPhase3RunTestCaseBonding(6)
+ }
+ // iopPhase3RunTestCaseSecurity(iopPhase3IndexStartChildrenTest, 0)
}
+
POSITION_TEST_IOP3_CACHING -> {
if (characteristicIOPPhase3IOPTestCaching != null) {
- getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![0].characteristic = characteristicIOPPhase3IOPTestCaching
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![0].characteristic =
+ characteristicIOPPhase3IOPTestCaching
readCharacteristic(characteristicIOPPhase3IOPTestCaching)
} else if (characteristicIOPPhase3IOPTestServiceChangedIndication != null) {
- getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![1].characteristic = characteristicIOPPhase3IOPTestServiceChangedIndication
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![1].characteristic =
+ characteristicIOPPhase3IOPTestServiceChangedIndication
readCharacteristic(characteristicIOPPhase3IOPTestServiceChangedIndication)
}
}
@@ -1162,20 +1483,28 @@ class IOPTestActivity : AppCompatActivity() {
POSITION_TEST_DISCOVER_SERVICE -> {
getSiliconLabsTestInfo().firmwareVersion = parseFirmwareVersion(payload)
}
+
POSITION_TEST_IOP3_OTA_ACK -> {
getSiliconLabsTestInfo().firmwareAckVersion = parseFirmwareVersion(payload)
}
+
POSITION_TEST_IOP3_OTA_WITHOUT_ACK -> {
getSiliconLabsTestInfo().firmwareUnackVersion = parseFirmwareVersion(payload)
}
- else -> { }
+
+ else -> {}
}
readCharacteristic(testParametersService?.characteristics?.get(1))
}
private fun getFirmwareVersion(): String {
- for (fwString in listOf(getSiliconLabsTestInfo().firmwareUnackVersion, getSiliconLabsTestInfo().firmwareAckVersion)) {
- if (fwString != "") { return fwString }
+ for (fwString in listOf(
+ getSiliconLabsTestInfo().firmwareUnackVersion,
+ getSiliconLabsTestInfo().firmwareAckVersion
+ )) {
+ if (fwString != "") {
+ return fwString
+ }
}
return getSiliconLabsTestInfo().firmwareVersion
}
@@ -1187,31 +1516,40 @@ class IOPTestActivity : AppCompatActivity() {
getSiliconLabsTestInfo().iopBoard = IopBoard.fromBoardCode(payload[0])
payloadIndex = 2
}
+
else -> readCharacteristic(getModelNumberStringCharacteristic())
}
getSiliconLabsTestInfo().connectionParameters = ConnectionParameters(
- mtu = Converters.calculateDecimalValue(
- payload.copyOfRange(payloadIndex, payloadIndex+2), isBigEndian = false),
- pdu = Converters.calculateDecimalValue(
- payload.copyOfRange(payloadIndex+2, payloadIndex+4), isBigEndian = false),
- interval = Converters.calculateDecimalValue(
- payload.copyOfRange(payloadIndex+4, payloadIndex+6), isBigEndian = false).
- toDouble().times(1.25), // Conversion of sent int representation to actual double value in ms
- slaveLatency = Converters.calculateDecimalValue(
- payload.copyOfRange(payloadIndex+6, payloadIndex+8), isBigEndian = false),
- supervisionTimeout = Converters.calculateDecimalValue(
- payload.copyOfRange(payloadIndex+8, payloadIndex+10), isBigEndian = false)
- .times(10), // Conversion of sent int representation to actual value in ms
+ mtu = Converters.calculateDecimalValue(
+ payload.copyOfRange(payloadIndex, payloadIndex + 2), isBigEndian = false
+ ),
+ pdu = Converters.calculateDecimalValue(
+ payload.copyOfRange(payloadIndex + 2, payloadIndex + 4), isBigEndian = false
+ ),
+ interval = Converters.calculateDecimalValue(
+ payload.copyOfRange(payloadIndex + 4, payloadIndex + 6), isBigEndian = false
+ ).toDouble()
+ .times(1.25), // Conversion of sent int representation to actual double value in ms
+ slaveLatency = Converters.calculateDecimalValue(
+ payload.copyOfRange(payloadIndex + 6, payloadIndex + 8), isBigEndian = false
+ ),
+ supervisionTimeout = Converters.calculateDecimalValue(
+ payload.copyOfRange(payloadIndex + 8, payloadIndex + 10), isBigEndian = false
+ )
+ .times(10), // Conversion of sent int representation to actual value in ms
)
- if(mIndexRunning == POSITION_TEST_DISCOVER_SERVICE) {
+ if (mIndexRunning == POSITION_TEST_DISCOVER_SERVICE) {
mIndexStartChildrenTest = 0
- finishItemTest(POSITION_TEST_DISCOVER_SERVICE, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_DISCOVER_SERVICE])
+ finishItemTest(
+ POSITION_TEST_DISCOVER_SERVICE,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_DISCOVER_SERVICE]
+ )
Log.d(TAG, "convertValuesParameters(), finishItemTest(POSITION_TEST_DISCOVER_SERVICE)")
}
}
- private fun parseFirmwareVersion(payload: ByteArray) : String {
+ private fun parseFirmwareVersion(payload: ByteArray): String {
return if (payload.size < 8) "3.2.1" /* Old, incompatible method for numbering versions. */
else StringBuilder().apply {
append(Converters.calculateDecimalValue(payload.copyOfRange(0, 2), isBigEndian = false))
@@ -1273,7 +1611,10 @@ class IOPTestActivity : AppCompatActivity() {
myOutWriter = OutputStreamWriter(fOut)
myOutWriter.write(getDataLog())
} catch (e: Exception) {
- Log.e(TAG, e.localizedMessage ?: "saveDataTestToFile(), OutputStreamWriter exception")
+ Log.e(
+ TAG,
+ e.localizedMessage ?: "saveDataTestToFile(), OutputStreamWriter exception"
+ )
} finally {
myOutWriter?.close()
}
@@ -1305,7 +1646,11 @@ class IOPTestActivity : AppCompatActivity() {
private fun shareLogDataTestByEmail(fileLocation: String) {
try {
- val uri = FileProvider.getUriForFile(this, applicationContext.packageName + ".provider", File(fileLocation))
+ val uri = FileProvider.getUriForFile(
+ this,
+ applicationContext.packageName + ".provider",
+ File(fileLocation)
+ )
val message = "Please check the attachment to get the log file."
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
@@ -1343,56 +1688,107 @@ class IOPTestActivity : AppCompatActivity() {
for (i in uuids.indices) {
if (cUuid.equals(uuids[i].toString(), ignoreCase = true)) {
matchChar = uuids[i].id
- Log.d(TAG, "Run TestCase [" + (matchChar + 3) + "] at characteristic " + uuids[i].toString())
+ Log.d(
+ TAG,
+ "Run TestCase [" + (matchChar + 3) + "] at characteristic " + uuids[i].toString()
+ )
break
}
}
when (matchChar) {
- CommonUUID.ID_READ_ONLY_LENGTH_1, CommonUUID.ID_READ_ONLY_LENGTH_255 -> readCharacteristic(childrenItem.characteristic)
- CommonUUID.ID_WRITE_ONLY_LENGTH_1, CommonUUID.ID_WRITE_WITHOUT_RESPONSE_LENGTH_1 -> writeValueToCharacteristic(childrenItem.characteristic, writeHexForMaxLengthByte(Common.WRITE_VALUE_0, Common.WRITE_LENGTH_1), null)
- CommonUUID.ID_WRITE_ONLY_LENGTH_255, CommonUUID.ID_WRITE_WITHOUT_RESPONSE_LENGTH_255 -> writeValueToCharacteristic(childrenItem.characteristic, writeHexForMaxLengthByte(Common.WRITE_VALUE_0, Common.WRITE_LENGTH_255), null)
+ CommonUUID.ID_READ_ONLY_LENGTH_1, CommonUUID.ID_READ_ONLY_LENGTH_255 -> readCharacteristic(
+ childrenItem.characteristic
+ )
+
+ CommonUUID.ID_WRITE_ONLY_LENGTH_1, CommonUUID.ID_WRITE_WITHOUT_RESPONSE_LENGTH_1 -> writeValueToCharacteristic(
+ childrenItem.characteristic,
+ writeHexForMaxLengthByte(Common.WRITE_VALUE_0, Common.WRITE_LENGTH_1),
+ null
+ )
+
+ CommonUUID.ID_WRITE_ONLY_LENGTH_255, CommonUUID.ID_WRITE_WITHOUT_RESPONSE_LENGTH_255 -> writeValueToCharacteristic(
+ childrenItem.characteristic,
+ writeHexForMaxLengthByte(Common.WRITE_VALUE_0, Common.WRITE_LENGTH_255),
+ null
+ )
+
CommonUUID.ID_NOTIFICATION_LENGTH_1, CommonUUID.ID_NOTIFICATION_LENGTH_MTU_3 -> {
setTimeStart(childrenItem.characteristic)
setNotificationForCharacteristic(childrenItem.characteristic, Notifications.NOTIFY)
}
+
CommonUUID.ID_INDICATE_LENGTH_1, CommonUUID.ID_INDICATE_LENGTH_MTU_3 -> {
setTimeStart(childrenItem.characteristic)
setIndicationProperty(childrenItem.characteristic, Notifications.INDICATE)
}
+
CommonUUID.ID_IOP_TEST_LENGTH_1, CommonUUID.ID_IOP_TEST_USER_LEN_1 -> if (!childrenItem.isWriteCharacteristic) {
- writeValueToCharacteristic(childrenItem.characteristic, writeHexForMaxLengthByte(Common.WRITE_VALUE_55, Common.WRITE_LENGTH_1), null)
+ writeValueToCharacteristic(
+ childrenItem.characteristic,
+ writeHexForMaxLengthByte(Common.WRITE_VALUE_55, Common.WRITE_LENGTH_1),
+ null
+ )
} else {
readCharacteristic(childrenItem.characteristic)
}
+
CommonUUID.ID_IOP_TEST_LENGTH_255, CommonUUID.ID_IOP_TEST_USER_LEN_255 -> if (!childrenItem.isWriteCharacteristic) {
- writeValueToCharacteristic(childrenItem.characteristic, null, Converters.decToByteArray(createDataTestCaseLength255(mtuValue)))
+ writeValueToCharacteristic(
+ childrenItem.characteristic,
+ null,
+ Converters.decToByteArray(createDataTestCaseLength255(mtuValue))
+ )
} else {
readCharacteristic(childrenItem.characteristic)
}
+
CommonUUID.ID_IOP_TEST_LENGTH_VARIABLE_4, CommonUUID.ID_IOP_TEST_USER_LEN_VARIABLE_4 -> // write length 1
- if (childrenItem.getLstValueItemTest().isEmpty() && !childrenItem.isWriteCharacteristic) {
- writeValueToCharacteristic(childrenItem.characteristic, writeHexForMaxLengthByte(Common.WRITE_VALUE_55, Common.WRITE_LENGTH_1), null)
- } else if (childrenItem.getLstValueItemTest().isEmpty() && childrenItem.isWriteCharacteristic) {
+ if (childrenItem.getLstValueItemTest()
+ .isEmpty() && !childrenItem.isWriteCharacteristic
+ ) {
+ writeValueToCharacteristic(
+ childrenItem.characteristic,
+ writeHexForMaxLengthByte(Common.WRITE_VALUE_55, Common.WRITE_LENGTH_1),
+ null
+ )
+ } else if (childrenItem.getLstValueItemTest()
+ .isEmpty() && childrenItem.isWriteCharacteristic
+ ) {
childrenItem.isWriteCharacteristic = false
childrenItem.statusWrite = -1
readCharacteristic(childrenItem.characteristic)
} else if (childrenItem.getLstValueItemTest().size == 1 && !childrenItem.isWriteCharacteristic) {
childrenItem.statusRead = -1
childrenItem.isReadCharacteristic = false
- writeValueToCharacteristic(childrenItem.characteristic, writeHexForMaxLengthByte(Common.WRITE_VALUE_66, Common.WRITE_LENGTH_4), null)
+ writeValueToCharacteristic(
+ childrenItem.characteristic,
+ writeHexForMaxLengthByte(Common.WRITE_VALUE_66, Common.WRITE_LENGTH_4),
+ null
+ )
} else if (childrenItem.getLstValueItemTest().size == 1 && childrenItem.isWriteCharacteristic) {
readCharacteristic(childrenItem.characteristic)
}
+
CommonUUID.ID_IOP_TEST_CONST_LENGTH_1 -> if (!childrenItem.isReadCharacteristic) {
readCharacteristic(childrenItem.characteristic)
} else {
- writeValueToCharacteristic(childrenItem.characteristic, writeHexForMaxLengthByte(Common.WRITE_VALUE_55, Common.WRITE_LENGTH_1), null)
+ writeValueToCharacteristic(
+ childrenItem.characteristic,
+ writeHexForMaxLengthByte(Common.WRITE_VALUE_55, Common.WRITE_LENGTH_1),
+ null
+ )
}
+
CommonUUID.ID_IOP_TEST_CONST_LENGTH_255 -> if (!childrenItem.isReadCharacteristic) {
readCharacteristic(childrenItem.characteristic)
} else {
- writeValueToCharacteristic(childrenItem.characteristic, null, Converters.decToByteArray(createDataTestCaseLength255(mtuValue)))
+ writeValueToCharacteristic(
+ childrenItem.characteristic,
+ null,
+ Converters.decToByteArray(createDataTestCaseLength255(mtuValue))
+ )
}
+
else -> {
}
}
@@ -1414,7 +1810,9 @@ class IOPTestActivity : AppCompatActivity() {
*/
private fun checkNextTestCase(characteristic: BluetoothGattCharacteristic?, type: Int) {
if (characteristic != null) {
- for (itemChildrenTest: ChildrenItemTestInfo in getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!) {
+ for (itemChildrenTest: ChildrenItemTestInfo in getListChildrenItemTestCase(
+ POSITION_TEST_SERVICE
+ )!!) {
if (itemChildrenTest.characteristic?.uuid.toString() == characteristic.uuid.toString()) {
if (type == 1) {
itemChildrenTest.isReadCharacteristic = true
@@ -1422,47 +1820,73 @@ class IOPTestActivity : AppCompatActivity() {
itemChildrenTest.isWriteCharacteristic = true
}
if (CommonUUID.Characteristic.IOP_TEST_LENGTH_1.toString() == characteristic.uuid.toString() || CommonUUID.Characteristic.IOP_TEST_LENGTH_255.toString() == characteristic.uuid.toString() || CommonUUID.Characteristic.IOP_TEST_CONST_LENGTH_1.toString() == characteristic.uuid.toString() || CommonUUID.Characteristic.IOP_TEST_CONST_LENGTH_255.toString() == characteristic.uuid.toString() || CommonUUID.Characteristic.IOP_TEST_USER_LEN_1.toString() == characteristic.uuid.toString() || CommonUUID.Characteristic.IOP_TEST_USER_LEN_255.toString() == characteristic.uuid.toString()) {
- mIndexStartChildrenTest = if (itemChildrenTest.isReadCharacteristic && itemChildrenTest.isWriteCharacteristic) {
- getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest) + 1
- } else {
- getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest)
- }
+ mIndexStartChildrenTest =
+ if (itemChildrenTest.isReadCharacteristic && itemChildrenTest.isWriteCharacteristic) {
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ ) + 1
+ } else {
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ )
+ }
} else if (CommonUUID.Characteristic.NOTIFICATION_LENGTH_1.toString() == characteristic.uuid.toString()) {
if (isDisabled) {
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest)
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ )
isDisabled = false
} else {
if (itemChildrenTest.statusChildrenTest) {
countReTest = 0
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest) + 1
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ ) + 1
isDisabled = false
} else {
countReTest++
if (countReTest > 5) {
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest) + 1
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ ) + 1
isDisabled = false
countReTest = 0
} else {
isDisabled = true
- setNotificationForCharacteristic(characteristic, Notifications.DISABLED)
+ setNotificationForCharacteristic(
+ characteristic,
+ Notifications.DISABLED
+ )
return
}
}
}
} else if (CommonUUID.Characteristic.INDICATE_LENGTH_1.toString() == characteristic.uuid.toString()) {
if (isDisabled) {
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest)
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ )
isDisabled = false
} else {
if (itemChildrenTest.statusChildrenTest) {
countReTest = 0
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest) + 1
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ ) + 1
isDisabled = false
} else {
countReTest++
if (countReTest > 5) {
countReTest = 0
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest) + 1
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ ) + 1
isDisabled = false
} else {
isDisabled = true
@@ -1473,21 +1897,35 @@ class IOPTestActivity : AppCompatActivity() {
}
} else if (CommonUUID.Characteristic.IOP_TEST_LENGTH_VARIABLE_4.toString() == characteristic.uuid.toString() || CommonUUID.Characteristic.IOP_TEST_USER_LEN_VARIABLE_4.toString() == characteristic.uuid.toString()) {
if (itemChildrenTest.getLstValueItemTest().size > 1 && itemChildrenTest.isReadCharacteristic) {
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest) + 1
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ ) + 1
if ((CommonUUID.Characteristic.IOP_TEST_USER_LEN_VARIABLE_4.toString() == characteristic.uuid.toString())) {
- finishItemTest(POSITION_TEST_SERVICE, getItemTestCaseInfo(POSITION_TEST_SERVICE))
+ finishItemTest(
+ POSITION_TEST_SERVICE,
+ getItemTestCaseInfo(POSITION_TEST_SERVICE)
+ )
}
} else {
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest)
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ )
}
} else {
- mIndexStartChildrenTest = getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(itemChildrenTest) + 1
+ mIndexStartChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_SERVICE)!!.indexOf(
+ itemChildrenTest
+ ) + 1
}
break
}
}
if (mIndexRunning == POSITION_TEST_IOP3_SECURITY) {
- for (itemChildrenTest: ChildrenItemTestInfo in getListChildrenItemTestCase(POSITION_TEST_IOP3_SECURITY)!!) {
+ for (itemChildrenTest: ChildrenItemTestInfo in getListChildrenItemTestCase(
+ POSITION_TEST_IOP3_SECURITY
+ )!!) {
if (itemChildrenTest.characteristic?.uuid.toString() == characteristic.uuid.toString()) {
handler?.removeCallbacks(iopSecurityRunnable)
if (type == 1) {
@@ -1495,11 +1933,22 @@ class IOPTestActivity : AppCompatActivity() {
}
if (CommonUUID.Characteristic.IOP_TEST_SECURITY_BONDING.toString() != (characteristic.uuid.toString())) {
iopPhase3IndexStartChildrenTest++
- Log.d(TAG, "iopPhase3IndexStartChildrenTest $iopPhase3IndexStartChildrenTest")
+ Log.d(
+ TAG,
+ "iopPhase3IndexStartChildrenTest $iopPhase3IndexStartChildrenTest"
+ )
showDetailInformationTest(testCaseCount++, false)
iopPhase3RunTestCaseSecurity(iopPhase3IndexStartChildrenTest, 1)
- } else {
+ } /*else {
finishItemTest(POSITION_TEST_IOP3_SECURITY, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_SECURITY])
+ }*/
+ else {
+ Log.d("checkNextTestCase", "iopPhase3RunTestCaseBonding")
+ if (iopPhase3BondingStep < 8) {
+ iopPhase3RunTestCaseBonding(iopPhase3BondingStep + 1)
+ }
+
+ showDetailInformationTest(testCaseCount++, false)
}
}
}
@@ -1514,6 +1963,7 @@ class IOPTestActivity : AppCompatActivity() {
}
}
}
+
}
if (mIndexStartChildrenTest <= 17) {
runChildrenTestCase(mIndexStartChildrenTest)
@@ -1534,7 +1984,11 @@ class IOPTestActivity : AppCompatActivity() {
/**
* Create values for control characteristic
*/
- private fun iopPhase3WriteControlBytes(throughput: Int, security: Int, caching: Int): ByteArray {
+ private fun iopPhase3WriteControlBytes(
+ throughput: Int,
+ security: Int,
+ caching: Int
+ ): ByteArray {
val hex = ByteArray(3)
hex[0] = throughput.toByte()
hex[1] = security.toByte()
@@ -1542,6 +1996,85 @@ class IOPTestActivity : AppCompatActivity() {
return hex
}
+ private fun iopPhase3RunTestCaseBonding(step: Int) {
+ Log.d("iopPhase3RunTestCaseBonding", "step $step")
+ iopPhase3BondingStep = step
+ val CCCD_value = ByteArray(1)
+ val securityItem = getListChildrenItemTestCase(POSITION_TEST_IOP3_SECURITY)!![2]
+ Log.d(
+ "iopPhase3RunTestCaseBonding",
+ "uuid " + UUID.fromString(securityItem.characteristic!!.uuid.toString())
+ )
+ iopPhase3ExtraDescriptor =
+ securityItem.characteristic!!.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))
+ when (step) {
+ // write CCCD to different value from the default
+ 3 -> {
+ CCCD_value[0] = 1
+ iopPhase3ExtraDescriptor?.setValue(CCCD_value)
+ mBluetoothGatt?.writeDescriptor(iopPhase3ExtraDescriptor)
+
+ mBluetoothGatt?.readDescriptor(iopPhase3ExtraDescriptor)
+ read_CCCD_value = iopPhase3ExtraDescriptor?.getValue()!!.copyOf()
+ }
+
+ // disconnect
+ 4 -> {
+
+ disconnectGatt(mBluetoothGatt)
+ // reconnect(4000)
+ //connectToDevice(mBluetoothDevice)
+ /* writeValueToCharacteristic(
+ characteristicIOPPhase3Control,
+ null,
+ iopPhase3WriteControlBytes(0, 4, 0))
+ Log.d("iopPhase3RunTestCaseBonding", "Set Control Characteristic for Security")*/
+ }
+
+ 6 -> {
+ mBluetoothGatt?.readDescriptor(iopPhase3ExtraDescriptor)
+ Log.d("CASE 6: iopPhase3RunTestCaseBonding", "read CCCD:" + read_CCCD_value[0])
+ // Mobile read CCCD. (Pass: if the CCCD value is the same as the value written before bond ).
+ if (read_CCCD_value[0].toInt() == 1) {
+ } else {
+ updateDataTestFailed(POSITION_TEST_IOP3_SECURITY)
+ isCCCDPass = false
+ finishItemTest(
+ POSITION_TEST_IOP3_SECURITY,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_SECURITY]
+ )
+ }
+ }
+
+ // Mobile write value 0xBB (0xBB or 0x00) to CCCD. (Pass: if the CCCD value was written in last step).
+ 7 -> {
+ Log.d("CASE 7: iopPhase3RunTestCaseBonding", "Write value 0x00 to CCCD")
+ CCCD_value[0] = 0
+ iopPhase3ExtraDescriptor?.setValue(CCCD_value)
+ mBluetoothGatt?.writeDescriptor(iopPhase3ExtraDescriptor)
+ }
+
+ 8 -> {
+ mBluetoothGatt?.readDescriptor(iopPhase3ExtraDescriptor)
+ read_CCCD_value = iopPhase3ExtraDescriptor?.getValue()!!.copyOf()
+ Log.d("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) {
+ } else {
+ isCCCDPass = false
+ updateDataTestFailed(POSITION_TEST_IOP3_SECURITY)
+ }
+ finishItemTest(
+ POSITION_TEST_IOP3_SECURITY,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_SECURITY]
+ )
+ }
+
+ else -> {
+ }
+ }
+ }
+
private fun iopPhase3RunTestCaseSecurity(index: Int, isControl: Int) {
iopPhase3IndexStartChildrenTest = index
isConnecting = false
@@ -1552,7 +2085,10 @@ class IOPTestActivity : AppCompatActivity() {
for (i in uuids.indices) {
if (cUuid.equals(uuids[i].toString(), ignoreCase = true)) {
matchChar = uuids[i].id
- Log.d(TAG, "Run TestCase [7." + (matchChar - CommonUUID.ID_IOP_TEST_PHASE3_THROUGHPUT) + "] at Characteristic " + uuids[i].toString())
+ Log.d(
+ TAG,
+ "Run TestCase [7." + (matchChar - CommonUUID.ID_IOP_TEST_PHASE3_THROUGHPUT) + "] at Characteristic " + uuids[i].toString()
+ )
break
}
}
@@ -1561,42 +2097,65 @@ class IOPTestActivity : AppCompatActivity() {
CommonUUID.ID_IOP_TEST_PHASE3_SECURITY_AUTHENTICATION,
CommonUUID.ID_IOP_TEST_PHASE3_SECURITY_BONDING ->
if (isControl == 1) {
- countReTest = 0
- handler?.postDelayed(iopSecurityRunnable, 60000)
- writeValueToCharacteristic(
+ if (iopPhase3BondingStep == 2) {
+ countReTest = 0
+ handler?.postDelayed(iopSecurityRunnable, 60000)
+ writeValueToCharacteristic(
characteristicIOPPhase3Control,
null,
- iopPhase3WriteControlBytes(0, matchChar - CommonUUID.ID_IOP_TEST_PHASE3_CONTROL - 1, 0))
- Log.d(TAG, "Set Control Characteristic for Security")
+ iopPhase3WriteControlBytes(
+ 0,
+ matchChar - CommonUUID.ID_IOP_TEST_PHASE3_CONTROL - 1,
+ 0
+ )
+ )
+ Log.d(TAG, "Set Control Characteristic for Security")
+ } else {
+ //Mobile read CCCD
+ iopPhase3RunTestCaseBonding(6)
+ }
} else if (!securityItem.isReadCharacteristic) {
Log.d(TAG, "Read Security Characteristic $cUuid")
readCharacteristic(securityItem.characteristic)
}
- else -> {
- }
+
+ else -> {
+ }
}
}
+
private fun iopPhase3RunTestCaseThroughput(isControl: Int) {
- Log.d(TAG, "Run TestCase [6] at Characteristic " + characteristicIOPPhase3Throughput?.uuid.toString())
+ Log.d(
+ TAG,
+ "Run TestCase [6] at Characteristic " + characteristicIOPPhase3Throughput?.uuid.toString()
+ )
if (isControl == 1) {
writeValueToCharacteristic(
- characteristicIOPPhase3Control,
- null,
- iopPhase3WriteControlBytes(1, 0, 0))
+ characteristicIOPPhase3Control,
+ null,
+ iopPhase3WriteControlBytes(1, 0, 0)
+ )
Log.d(TAG, "Set Control Characteristic for Throughput")
} else {
Log.d(TAG, "set Notification enable for Throughput")
mEndThroughputNotification = false
- setNotificationForCharacteristic(characteristicIOPPhase3Throughput, Notifications.NOTIFY)
+ setNotificationForCharacteristic(
+ characteristicIOPPhase3Throughput,
+ Notifications.NOTIFY
+ )
mStartTimeThroughput = System.currentTimeMillis()
handler?.postDelayed({
mEndTimeThroughput = System.currentTimeMillis()
- mByteSpeed = ((mByteNumReceived * 1000) / (mEndTimeThroughput - mStartTimeThroughput)).toInt()
+ mByteSpeed =
+ ((mByteNumReceived * 1000) / (mEndTimeThroughput - mStartTimeThroughput)).toInt()
Log.d(TAG, "set Notification disable for throughput")
Log.d(TAG, "Throughput is $mByteSpeed Bytes/sec")
try {
- setNotificationForCharacteristic(characteristicIOPPhase3Throughput, Notifications.DISABLED)
+ setNotificationForCharacteristic(
+ characteristicIOPPhase3Throughput,
+ Notifications.DISABLED
+ )
} catch (e: Exception) {
Log.e(TAG, "Error Notification disable for throughput")
}
@@ -1605,6 +2164,118 @@ class IOPTestActivity : AppCompatActivity() {
}
}
+ private fun iopPhase3RunTestCaseLEPrivacy(isControl: Int) {
+ Log.d(
+ TAG,
+ "Run TestCase [8] at Characteristic " + characteristicIOPPhase3Throughput?.uuid.toString()
+ )
+
+ if (isControl == 1) {
+ connectToDevice(mBluetoothDevice)
+
+ writeValueToCharacteristic(
+ characteristicIOPPhase3Control,
+ null,
+ iopPhase3WriteControlBytes(0, 4, 0)
+ ) { success ->
+ if (success) {
+ handler?.postDelayed({
+ Log.d(TAG, "Write operation successful")
+
+ connectToDevice(mBluetoothDevice,
+ onConnectionSuccess = {
+ // Code to execute after successful connection
+ handler?.postDelayed({
+ if (isConnected) {
+ Log.d(TAG, "Connection successful")
+ // Perform further actions here
+
+ Log.d(TAG, "Set Control Characteristic for LE Privacy")
+ if (isServiceChangedIndication == 1) {
+ try {
+ val connectionState = mBluetoothDevice?.bondState
+ Log.d(TAG, "" + connectionState)
+
+
+ when (connectionState) {
+ BluetoothDevice.BOND_BONDED -> {
+ // Device is bonded (connected)
+ Log.d(TAG, "Device is bonded (connected)")
+ setNotificationForCharacteristic(
+ characteristicIOPPhase3ServiceChanged,
+ Notifications.INDICATE
+ )
+ getItemTestCaseInfo(
+ POSITION_TEST_IOP3_LE_PRIVACY
+ ).setStatusTest(Common.IOP3_TC_STATUS_PASS)
+
+ }
+
+ BluetoothDevice.BOND_BONDING -> {
+ // Device is in the process of bonding (connecting)
+ // Handle this state if needed
+ Log.d(
+ TAG,
+ "Device is in the process of bonding (connecting)"
+ )
+ }
+
+ BluetoothDevice.BOND_NONE -> {
+ // Device is not bonded (not connected)
+ // Handle this state if needed
+ Log.d(
+ TAG,
+ "Device is not bonded (not connected)"
+ )
+ Log.d(
+ TAG,
+ "Connection is not trusted, not bonded"
+ )
+ updateDataTestFailed(
+ POSITION_TEST_IOP3_LE_PRIVACY
+ )
+ // handler?.removeCallbacks(iopLEPrivacyRunnable)
+ }
+ }
+
+ } catch (e: Exception) {
+ Log.d(TAG, "exception $e")
+ updateDataTestFailed(POSITION_TEST_IOP3_LE_PRIVACY)
+ }
+
+ } else {
+ Log.d(
+ TAG,
+ "isServiceChangedIndication $isServiceChangedIndication"
+ )
+ updateDataTestFailed(POSITION_TEST_IOP3_LE_PRIVACY)
+ }
+ }
+ }, 15000)
+
+
+ },
+ onConnectionFailure = {
+ // Code to handle connection failure
+ Log.e(TAG, "Connection failed")
+ updateDataTestFailed(POSITION_TEST_IOP3_LE_PRIVACY)
+ // Perform actions to handle the failure
+ }
+ )
+ }, CONNECTION_PERIOD)
+
+
+ } else {
+ // Write operation failed, handle accordingly
+ Log.e(TAG, "Write operation failed")
+ }
+ }
+
+ } else {
+ Log.d(TAG, "is control $isControl")
+ }
+ }
+
private fun iopPhase3RunTestCaseCaching(isControl: Int) {
Log.d(TAG, "Run TestCase [8]")
val itemChildrenTest: ChildrenItemTestInfo
@@ -1612,19 +2283,22 @@ class IOPTestActivity : AppCompatActivity() {
if (isControl == 1) {
if (isServiceChangedIndication == 1) {
writeValueToCharacteristic(
- characteristicIOPPhase3Control,
- null,
- iopPhase3WriteControlBytes(0, 0, 1))
+ characteristicIOPPhase3Control,
+ null,
+ iopPhase3WriteControlBytes(0, 0, 1)
+ )
Log.d(TAG, "Set Control Characteristic for Service Changed Indications")
} else {
writeValueToCharacteristic(
- characteristicIOPPhase3Control,
- null,
- iopPhase3WriteControlBytes(0, 0, 2))
+ characteristicIOPPhase3Control,
+ null,
+ iopPhase3WriteControlBytes(0, 0, 2)
+ )
Log.d(TAG, "Set Control Characteristic for GATT Caching")
}
} else {
- itemChildrenTest = getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![isServiceChangedIndication]
+ itemChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![isServiceChangedIndication]
itemChildrenTest.statusRunTest = 0
itemChildrenTest.startTimeTest = System.currentTimeMillis()
handler?.postDelayed(iopCachingRunnable, 90000)
@@ -1632,7 +2306,10 @@ class IOPTestActivity : AppCompatActivity() {
val bonded = mBluetoothGatt?.device?.bondState == BluetoothDevice.BOND_BONDED
if (bonded) {
Log.d(TAG, "Subscribe Indication for Service Changed")
- setNotificationForCharacteristic(characteristicIOPPhase3ServiceChanged, Notifications.INDICATE)
+ setNotificationForCharacteristic(
+ characteristicIOPPhase3ServiceChanged,
+ Notifications.INDICATE
+ )
} else {
Log.d(TAG, "Connection is not trusted, not bonded")
iopCachingFailed()
@@ -1640,23 +2317,32 @@ class IOPTestActivity : AppCompatActivity() {
}
} else {
Log.d(TAG, "Set on Client Supported Features")
- writeValueToCharacteristic(characteristicIOPPhase3ClientSupportedFeatures, "01", null)
+ writeValueToCharacteristic(
+ characteristicIOPPhase3ClientSupportedFeatures,
+ "01",
+ null
+ )
}
}
}
+
private val iopCachingRunnable = Runnable {
Log.d(TAG, "iopCachingRunnable")
iopCachingFailed()
}
private fun iopCachingFailed() {
- val itemChildrenTest = getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![isServiceChangedIndication]
+ val itemChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_CACHING)!![isServiceChangedIndication]
itemChildrenTest.statusRunTest = 1
itemChildrenTest.statusChildrenTest = false
itemChildrenTest.endTimeTest = System.currentTimeMillis()
getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING].setStatusTest(Common.IOP3_TC_STATUS_FAILED)
- finishItemTest(POSITION_TEST_IOP3_CACHING, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING])
+ finishItemTest(
+ POSITION_TEST_IOP3_CACHING,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING]
+ )
}
private fun retryIOP3Failed(index: Int, mCountReTest: Int) {
@@ -1664,9 +2350,14 @@ class IOPTestActivity : AppCompatActivity() {
updateDataTestFailed(index)
} else if (index == POSITION_TEST_CONNECTION) {
Log.d(TAG, "retryIOP3Failed index $index")
- handler?.postDelayed({ finishItemTest(POSITION_TEST_CONNECTION, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_CONNECTION]) }, 1000)
+ handler?.postDelayed({
+ finishItemTest(
+ POSITION_TEST_CONNECTION,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_CONNECTION]
+ )
+ }, 1000)
} else {
- if (mCountReTest < 6) {
+ if (mCountReTest < 7) {
isConnecting = false
reconnect(2000)
} else {
@@ -1688,9 +2379,13 @@ class IOPTestActivity : AppCompatActivity() {
private val iopSecurityRunnable: Runnable = Runnable {
Log.d(TAG, "iopSecurityRunnable $iopPhase3IndexStartChildrenTest")
- val itemChildrenTest = getListChildrenItemTestCase(POSITION_TEST_IOP3_SECURITY)!![iopPhase3IndexStartChildrenTest]
+ val itemChildrenTest =
+ getListChildrenItemTestCase(POSITION_TEST_IOP3_SECURITY)!![iopPhase3IndexStartChildrenTest]
itemChildrenTest.statusRunTest = 1 // 0 running, 1 finish test
- Log.d(TAG, "iopSecurityRunnable $iopPhase3IndexStartChildrenTest, setStatusRunTest finish test")
+ Log.d(
+ TAG,
+ "iopSecurityRunnable $iopPhase3IndexStartChildrenTest, setStatusRunTest finish test"
+ )
itemChildrenTest.statusChildrenTest = false
Log.d(TAG, "setStatusChildrenTest false")
val itemTestCaseInfo = getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_SECURITY]
@@ -1711,19 +2406,23 @@ class IOPTestActivity : AppCompatActivity() {
when (getSiliconLabsTestInfo().firmwareVersion) {
"3.2.1", "3.2.2", "3.2.3", "3.2.4" -> {
otaFileManager
- ?.apply { uploadMode = OtaFileManager.UploadMode.AUTO }
- ?.also { it.findGblFile(
- getSiliconLabsTestInfo().firmwareVersion,
- getSiliconLabsTestInfo().iopBoard,
- reliable
- ) }
+ ?.apply { uploadMode = OtaFileManager.UploadMode.AUTO }
+ ?.also {
+ it.findGblFile(
+ getSiliconLabsTestInfo().firmwareVersion,
+ getSiliconLabsTestInfo().iopBoard,
+ reliable
+ )
+ }
startOtaProcess()
}
+
else -> {
otaFileManager?.uploadMode = OtaFileManager.UploadMode.USER
- otaFileSelectionDialog = OtaFileSelectionDialog(listener = fileSelectionListener).also {
- it.show(supportFragmentManager, "ota_file_selection_dialog")
- }
+ otaFileSelectionDialog =
+ OtaFileSelectionDialog(listener = fileSelectionListener).also {
+ it.show(supportFragmentManager, "ota_file_selection_dialog")
+ }
}
}
@@ -1733,8 +2432,14 @@ class IOPTestActivity : AppCompatActivity() {
override fun onSelectFileButtonClicked() {
Intent(Intent.ACTION_GET_CONTENT)
.apply { type = "*/*" }
- .also { startActivityForResult(Intent.createChooser(it,
- getString(R.string.ota_choose_file)), GBL_FILE_CHOICE_REQUEST_CODE) }
+ .also {
+ startActivityForResult(
+ Intent.createChooser(
+ it,
+ getString(R.string.ota_choose_file)
+ ), GBL_FILE_CHOICE_REQUEST_CODE
+ )
+ }
}
override fun onOtaButtonClicked() {
@@ -1742,9 +2447,17 @@ class IOPTestActivity : AppCompatActivity() {
otaFileSelectionDialog?.dismiss()
startOtaProcess()
} ?: if (otaFileManager?.otaFilename != null) {
- Toast.makeText(this@IOPTestActivity, getString(R.string.incorrect_file), Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ this@IOPTestActivity,
+ getString(R.string.incorrect_file),
+ Toast.LENGTH_SHORT
+ ).show()
} else {
- Toast.makeText(this@IOPTestActivity, getString(R.string.no_file_chosen), Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ this@IOPTestActivity,
+ getString(R.string.no_file_chosen),
+ Toast.LENGTH_SHORT
+ ).show()
}
}
@@ -1769,20 +2482,24 @@ class IOPTestActivity : AppCompatActivity() {
}
}
- private fun isOtaNameCorrect(deviceName: String) : Boolean {
+ private fun isOtaNameCorrect(deviceName: String): Boolean {
return when {
otaFileManager?.uploadMode == OtaFileManager.UploadMode.AUTO && mIndexRunning == POSITION_TEST_IOP3_OTA_ACK -> {
deviceName.equals(OTA_DEVICE_NAME_AUTO_ACK, ignoreCase = true)
}
+
otaFileManager?.uploadMode == OtaFileManager.UploadMode.AUTO && mIndexRunning == POSITION_TEST_IOP3_OTA_WITHOUT_ACK -> {
deviceName.equals(OTA_DEVICE_NAME_AUTO_UNACK, ignoreCase = true)
}
+
otaFileManager?.uploadMode == OtaFileManager.UploadMode.USER && mIndexRunning == POSITION_TEST_IOP3_OTA_ACK -> {
deviceName.equals(OTA_DEVICE_NAME_USER_ACK, ignoreCase = true)
}
+
otaFileManager?.uploadMode == OtaFileManager.UploadMode.USER && mIndexRunning == POSITION_TEST_IOP3_OTA_WITHOUT_ACK -> {
deviceName.equals(OTA_DEVICE_NAME_USER_UNACK, ignoreCase = true)
}
+
else -> false
}
@@ -1808,12 +2525,14 @@ class IOPTestActivity : AppCompatActivity() {
handler?.postDelayed(WRITE_OTA_CONTROL_ZERO, 200)
}
}
+
"OTAUPLOAD" -> {
Log.d(OTA_UPLOAD, "Called")
//Check Services
val mBluetoothGattService = mBluetoothGatt?.getService(ota_service)
if (mBluetoothGattService != null) {
- val charac = mBluetoothGatt?.getService(ota_service)?.getCharacteristic(ota_data)
+ val charac =
+ mBluetoothGatt?.getService(ota_service)?.getCharacteristic(ota_data)
if (charac != null) {
charac.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
Log.d("Instance ID", "" + charac.instanceId)
@@ -1822,7 +2541,10 @@ class IOPTestActivity : AppCompatActivity() {
//Set info into UI OTA Progress
runOnUiThread {
- otaProgressDialog?.setProgressInfo(otaFileManager?.otaFilename, otaFileManager?.otaFile?.size)
+ otaProgressDialog?.setProgressInfo(
+ otaFileManager?.otaFilename,
+ otaFileManager?.otaFile?.size
+ )
animateLoading()
}
//Start OTA_data Upload in another thread
@@ -1837,15 +2559,18 @@ class IOPTestActivity : AppCompatActivity() {
}
}
}
+
"OTAEND" -> {
Log.d(TAG, "OTAEND Called")
handler?.postDelayed({ writeOtaControl(0x03.toByte()) }, 1000)
}
+
"DISCONNECTION" -> {
otaProcess = false
boolOTAbegin = false
disconnectGatt(mBluetoothGatt)
}
+
else -> {
}
}
@@ -1999,7 +2724,10 @@ class IOPTestActivity : AppCompatActivity() {
j++
}
pgss = ((pack + last).toFloat() / (otaFileManager?.otaFile!!.size - 1)) * 100
- Log.d("characte", "last: " + pack + " / " + (pack + last) + " : " + Converters.getHexValue(writearray))
+ Log.d(
+ "characte",
+ "last: " + pack + " / " + (pack + last) + " : " + Converters.getHexValue(writearray)
+ )
} else {
var j = 0
writearray = ByteArray(mtuDivisible)
@@ -2008,7 +2736,12 @@ class IOPTestActivity : AppCompatActivity() {
j++
}
pgss = ((pack + mtuDivisible).toFloat() / (otaFileManager?.otaFile!!.size - 1)) * 100
- Log.d("characte", "pack: " + pack + " / " + (pack + mtuDivisible) + " : " + Converters.getHexValue(writearray))
+ Log.d(
+ "characte",
+ "pack: " + pack + " / " + (pack + mtuDivisible) + " : " + Converters.getHexValue(
+ writearray
+ )
+ )
}
val charac = mBluetoothGatt?.getService(ota_service)?.getCharacteristic(ota_data)
charac?.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
@@ -2022,7 +2755,8 @@ class IOPTestActivity : AppCompatActivity() {
otaProgressDialog?.progressBar?.progress = pgss.toInt()
val datarate = String.format(Locale.US, kBits, bitrate)
otaProgressDialog?.dataRate?.text = datarate
- otaProgressDialog?.dataSize?.text = getString(R.string.iop_test_n_percent, pgss.toInt())
+ otaProgressDialog?.dataSize?.text =
+ getString(R.string.iop_test_n_percent, pgss.toInt())
}
}
} else {
@@ -2044,24 +2778,46 @@ class IOPTestActivity : AppCompatActivity() {
j++
if (j >= mtu - 3 || i >= (dataThread.size - 1)) {
var wait = System.nanoTime()
- val charac = mBluetoothGatt?.getService(ota_service)?.getCharacteristic(ota_data)
+ val charac =
+ mBluetoothGatt?.getService(ota_service)?.getCharacteristic(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(kBits, bitrate) + " - " + Converters.getHexValue(end))
+ Log.d(
+ "Progress",
+ "sent " + (i + 1) + " / " + dataThread.size + " - " + String.format(
+ "%.1f",
+ progress
+ ) + " % - " + String.format(
+ kBits,
+ bitrate
+ ) + " - " + Converters.getHexValue(end)
+ )
runOnUiThread {
- otaProgressDialog?.dataSize?.text = getString(R.string.iop_test_n_percent, progress.toInt())
+ otaProgressDialog?.dataSize?.text =
+ getString(R.string.iop_test_n_percent, progress.toInt())
otaProgressDialog?.progressBar?.progress = progress.toInt()
}
charac?.value = end
} else {
j = 0
- Log.d("Progress", "sent " + (i + 1) + " / " + dataThread.size + " - " + String.format("%.1f", progress) + " % - " + String.format(kBits, bitrate) + " - " + Converters.getHexValue(value))
+ Log.d(
+ "Progress",
+ "sent " + (i + 1) + " / " + dataThread.size + " - " + String.format(
+ "%.1f",
+ progress
+ ) + " % - " + String.format(
+ kBits,
+ bitrate
+ ) + " - " + Converters.getHexValue(value)
+ )
runOnUiThread {
- otaProgressDialog?.dataSize?.text = getString(R.string.iop_test_n_percent, progress.toInt())
+ otaProgressDialog?.dataSize?.text =
+ getString(R.string.iop_test_n_percent, progress.toInt())
otaProgressDialog?.progressBar?.progress = progress.toInt()
}
charac?.value = value
@@ -2107,7 +2863,18 @@ class IOPTestActivity : AppCompatActivity() {
*/
private fun homeKitOTAControl(instanceID: ByteArray) {
//WRITE CHARACTERISTIC FOR HOMEKIT
- val value = byteArrayOf(0x00, 0x02, 0xee.toByte(), instanceID[0], instanceID[1], 0x03, 0x00, 0x01, 0x01, 0x01)
+ val value = byteArrayOf(
+ 0x00,
+ 0x02,
+ 0xee.toByte(),
+ instanceID[0],
+ instanceID[1],
+ 0x03,
+ 0x00,
+ 0x01,
+ 0x01,
+ 0x01
+ )
writeGenericCharacteristic(ota_service, ota_control, value)
Log.d(TAG, "characteristic writting: " + Converters.getHexValue(value))
}
@@ -2115,13 +2882,19 @@ class IOPTestActivity : AppCompatActivity() {
/**
* WRITES BYTE ARRAY TO A GENERIC CHARACTERISTIC
*/
- private fun writeGenericCharacteristic(service: UUID?, characteristic: UUID?, value: ByteArray?): Boolean {
+ private fun writeGenericCharacteristic(
+ service: UUID?,
+ characteristic: UUID?,
+ value: ByteArray?
+ ): Boolean {
if (mBluetoothGatt != null) {
- val bluetoothGattCharacteristic = mBluetoothGatt?.getService(service)?.getCharacteristic(characteristic)
+ val bluetoothGattCharacteristic =
+ mBluetoothGatt?.getService(service)?.getCharacteristic(characteristic)
Log.d(TAG, "characteristic exists")
if (bluetoothGattCharacteristic != null) {
bluetoothGattCharacteristic.value = value
- bluetoothGattCharacteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
+ bluetoothGattCharacteristic.writeType =
+ BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
mBluetoothGatt?.writeCharacteristic(bluetoothGattCharacteristic)
Log.d(TAG, "characteristic written")
} else {
@@ -2152,24 +2925,52 @@ class IOPTestActivity : AppCompatActivity() {
Log.d(TAG, "onConnectionStateChange status $status - newState $newState")
when (newState) {
BluetoothGatt.STATE_CONNECTED -> {
+ Log.d(TAG, "onConnectionStateChange connected")
handler?.removeCallbacks(connectionRunnable)
isConnected = true
isTestFinished = false
if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_CONNECTION].getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING) {
Log.d(TAG, "onConnectionStateChange POSITION_TEST_CONNECTION")
- finishItemTest(POSITION_TEST_CONNECTION, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_CONNECTION])
+ finishItemTest(
+ POSITION_TEST_CONNECTION,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_CONNECTION]
+ )
} else {
if (!otaProcess) {
- Log.d(TAG, "onConnectionStateChange connected mIndexRunning $mIndexRunning")
+ Log.d(
+ TAG,
+ "onConnectionStateChange connected mIndexRunning $mIndexRunning"
+ )
mBluetoothGatt?.requestMtu(247)
+ handler?.postDelayed({
+ if (isConnected && mIndexRunning == 8) {
+ Log.d(
+ TAG,
+ "onConnectionStateChange connected mIndexRunningis 8"
+ )
+ isTestRunning = false
+ isTestFinished = true
+
+ getItemTestCaseInfo(POSITION_TEST_IOP3_LE_PRIVACY).setStatusTest(
+ Common.IOP3_TC_STATUS_PASS
+ )
+ runOnUiThread { updateUIFooter(isTestRunning) }
+ mListener?.updateUi()
+ }
+ }, CONNECTION_PERIOD)
+
} else { //After OTA process started
//get information
Log.d(TAG, "Device: " + gatt.device)
Log.d(TAG, "Device Name: " + gatt.device.name)
if (gatt.services.isEmpty()) {
handler?.postDelayed({
- mBluetoothGatt = null //It's going to be equal gatt in Discover Services Callback...
- Log.d(TAG, "onConnected, start Services Discovery: " + gatt.discoverServices())
+ mBluetoothGatt =
+ null //It's going to be equal gatt in Discover Services Callback...
+ Log.d(
+ TAG,
+ "onConnected, start Services Discovery: " + gatt.discoverServices()
+ )
}, 250)
discoverTimeout = true
@@ -2178,7 +2979,11 @@ class IOPTestActivity : AppCompatActivity() {
if (discoverTimeout) {
disconnectGatt(gatt)
runOnUiThread {
- Toast.makeText(baseContext, "DISCOVER SERVICES TIMEOUT", Toast.LENGTH_LONG).show()
+ Toast.makeText(
+ baseContext,
+ "DISCOVER SERVICES TIMEOUT",
+ Toast.LENGTH_LONG
+ ).show()
}
}
}, 25000)
@@ -2188,6 +2993,7 @@ class IOPTestActivity : AppCompatActivity() {
}
}
}
+
BluetoothGatt.STATE_DISCONNECTED -> {
Log.d(TAG, "Disconnected IOP Test device: " + System.currentTimeMillis())
isConnected = false
@@ -2203,7 +3009,10 @@ class IOPTestActivity : AppCompatActivity() {
}
} else {
if (!otaProcess && !isTestFinished) {
- Log.d(TAG, "onConnectionStateChange ota_process $otaProcess,isConnecting $isConnecting")
+ Log.d(
+ TAG,
+ "onConnectionStateChange ota_process $otaProcess,isConnecting $isConnecting"
+ )
if (mIndexRunning > POSITION_TEST_IOP3_OTA_WITHOUT_ACK || mIndexRunning < POSITION_TEST_IOP3_OTA_ACK) {
if (!isConnecting) {
isConnecting = true
@@ -2242,7 +3051,12 @@ class IOPTestActivity : AppCompatActivity() {
}
}
}
- BluetoothGatt.STATE_CONNECTING -> Log.d(TAG, "onConnectionStateChange Connecting...")
+
+ BluetoothGatt.STATE_CONNECTING -> Log.d(
+ TAG,
+ "onConnectionStateChange Connecting..."
+ )
+
else -> {
}
}
@@ -2261,7 +3075,11 @@ class IOPTestActivity : AppCompatActivity() {
discoverTimeout = false
if (status != 0) {
runOnUiThread {
- Toast.makeText(baseContext, ErrorCodes.getErrorName(status), Toast.LENGTH_LONG).show()
+ Toast.makeText(
+ baseContext,
+ ErrorCodes.getErrorName(status),
+ Toast.LENGTH_LONG
+ ).show()
updateDataTestFailed(mIndexRunning)
}
handler?.postDelayed({
@@ -2272,7 +3090,8 @@ class IOPTestActivity : AppCompatActivity() {
val otaServiceCheck = gatt.getService(ota_service) != null
if (otaServiceCheck) {
- val otaDataCheck = gatt.getService(ota_service).getCharacteristic(ota_data) != null
+ val otaDataCheck =
+ gatt.getService(ota_service).getCharacteristic(ota_data) != null
if (otaDataCheck) {
val homeKitCheck = gatt.getService(homekit_service) != null
if (!homeKitCheck) {
@@ -2299,12 +3118,20 @@ class IOPTestActivity : AppCompatActivity() {
}
}
- override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic,
+ status: Int
+ ) {
super.onCharacteristicRead(gatt, characteristic, status)
- Log.d(TAG, "onCharacteristicRead: " + characteristic.uuid.toString() + " status " + status)
+ Log.d(
+ TAG,
+ "onCharacteristicRead: " + characteristic.uuid.toString() + " status " + status
+ )
if (characteristic.uuid == GattCharacteristic.ModelNumberString.uuid) {
- getSiliconLabsTestInfo().iopBoard = IopBoard.fromBoardString(characteristic.getStringValue(0))
+ getSiliconLabsTestInfo().iopBoard =
+ IopBoard.fromBoardString(characteristic.getStringValue(0))
}
if (characteristic.service.uuid.toString() == CommonUUID.Service.TEST_PARAMETERS.toString()) {
@@ -2312,9 +3139,11 @@ class IOPTestActivity : AppCompatActivity() {
when (characteristic.uuid.toString()) {
CommonUUID.Characteristic.FIRMWARE_VERSION.toString() ->
readFirmwareVersion(characteristic.value)
+
CommonUUID.Characteristic.CONNECTION_PARAMETERS.toString() ->
readConnectionParameters(characteristic.value)
- else -> { }
+
+ else -> {}
}
} else {
nrTries = 0
@@ -2333,12 +3162,18 @@ class IOPTestActivity : AppCompatActivity() {
checkNextTestCase(characteristic, 1)
// type 1: CharacteristicRead, 2:CharacteristicWrite
if (mBluetoothGatt?.getService(ota_service) != null) {
- if (characteristic === mBluetoothGatt?.getService(ota_service)?.getCharacteristic(ota_control)) {
+ if (characteristic === mBluetoothGatt?.getService(ota_service)
+ ?.getCharacteristic(ota_control)
+ ) {
val value = characteristic.value
if (value[2] == 0x05.toByte()) {
Log.e("homekit_descriptor", "Insecure Connection")
runOnUiThread {
- Toast.makeText(this@IOPTestActivity, "Error: Not a Homekit Secure Connection", Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ this@IOPTestActivity,
+ "Error: Not a Homekit Secure Connection",
+ Toast.LENGTH_SHORT
+ ).show()
}
} else if (value[2] == 0x04.toByte()) {
Log.e("homekit_descriptor", "Wrong Address")
@@ -2360,7 +3195,11 @@ class IOPTestActivity : AppCompatActivity() {
}
}
- override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic,
+ status: Int
+ ) {
super.onCharacteristicWrite(gatt, characteristic, status)
Log.d(TAG, "onCharacteristicWrite: " + characteristic.uuid.toString())
Log.d(TAG, "onCharacteristicWrite: $status")
@@ -2371,7 +3210,10 @@ class IOPTestActivity : AppCompatActivity() {
if (characteristic.uuid == ota_control) { //OTA Control Callback Handling
if (characteristic.value.size == 1) {
if (characteristic.value[0] == 0x00.toByte()) {
- Log.e("Callback", "Control " + Converters.getHexValue(characteristic.value) + "status: " + status)
+ Log.e(
+ "Callback",
+ "Control " + Converters.getHexValue(characteristic.value) + "status: " + status
+ )
if (ota_mode && otaProcess) {
Log.e(OTA_UPLOAD, "Sent")
runOnUiThread(checkBeginRunnable)
@@ -2386,13 +3228,19 @@ class IOPTestActivity : AppCompatActivity() {
}
if (characteristic.value[0] == 0x03.toByte()) {
if (otaProcess) {
- Log.e("Callback", "Control " + Converters.getHexValue(characteristic.value) + "status: " + status)
+ Log.e(
+ "Callback",
+ "Control " + Converters.getHexValue(characteristic.value) + "status: " + status
+ )
runOnUiThread { otaProgressDialog?.btnOtaEnd?.isEnabled = true }
boolOTAbegin = false
}
}
} else {
- Log.i("OTA_Control", "Received: " + Converters.getHexValue(characteristic.value))
+ Log.i(
+ "OTA_Control",
+ "Received: " + Converters.getHexValue(characteristic.value)
+ )
if (characteristic.value[0].toInt() == 0x00 && characteristic.value[1].toInt() == 0x02) {
Log.i("HomeKit", "Reading OTA_Control...")
mBluetoothGatt?.readCharacteristic(characteristic)
@@ -2421,15 +3269,25 @@ class IOPTestActivity : AppCompatActivity() {
}
}
- override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt,
+ characteristic: BluetoothGattCharacteristic
+ ) {
super.onCharacteristicChanged(gatt, characteristic)
- Log.d(TAG, "onCharacteristicChanged: " + characteristic.uuid.toString() + " len:" + characteristic.value.size)
+ Log.d(
+ TAG,
+ "onCharacteristicChanged: " + characteristic.uuid.toString() + " len:" + characteristic.value.size
+ )
updateDataTest(characteristic, -1, -1)
checkNextTestCase(characteristic, 0)
// type 1: CharacteristicRead, 2:CharacteristicWrite, 0:Notify
}
- override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt,
+ descriptor: BluetoothGattDescriptor,
+ status: Int
+ ) {
super.onDescriptorRead(gatt, descriptor, status)
Log.d(TAG, "onDescriptorRead mIndexStartChildrenTest: $mIndexStartChildrenTest")
if (descriptor.uuid.toString() == homekit_descriptor.toString()) {
@@ -2440,9 +3298,24 @@ class IOPTestActivity : AppCompatActivity() {
Log.i("descriptor", "getValue " + Converters.getHexValue(descriptor.value))
}
}
+ if (iopPhase3ExtraDescriptor != null) {
+ if (descriptor.uuid.toString() == iopPhase3ExtraDescriptor!!.uuid.toString()) {
+ Log.d(
+ "iopPhase3RunTestCaseBonding",
+ "Descriptor getValue " + Converters.getHexValue(descriptor.value)
+ )
+ if (iopPhase3BondingStep < 8) {
+ iopPhase3RunTestCaseBonding(iopPhase3BondingStep + 1)
+ }
+ }
+ }
}
- override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt,
+ descriptor: BluetoothGattDescriptor,
+ status: Int
+ ) {
super.onDescriptorWrite(gatt, descriptor, status)
Log.d(TAG, "onDescriptorWrite status $status")
if (mIndexStartChildrenTest <= 17 && isDisabled) {
@@ -2451,11 +3324,28 @@ class IOPTestActivity : AppCompatActivity() {
} else if (mEndThroughputNotification) {
mEndThroughputNotification = false
if (status == 0) {
- finishItemTest(POSITION_TEST_IOP3_THROUGHPUT, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_THROUGHPUT])
+ finishItemTest(
+ POSITION_TEST_IOP3_THROUGHPUT,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_THROUGHPUT]
+ )
+ } else if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_LE_PRIVACY]
+ .getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING
+ ) {
+ iopPhase3RunTestCaseLEPrivacy(1)
+ }
+ /*} else if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING]
+ .getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING) {
+ iopPhase3RunTestCaseCaching(1) */
+ } else if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_LE_PRIVACY]
+ .getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING
+ ) {
+ iopPhase3RunTestCaseLEPrivacy(1)
+ } else if (iopPhase3ExtraDescriptor != null) {
+ if (descriptor.uuid.toString() == iopPhase3ExtraDescriptor!!.uuid.toString()) {
+ if (iopPhase3BondingStep < 8) {
+ iopPhase3RunTestCaseBonding(iopPhase3BondingStep + 1)
+ }
}
- /*} else if (getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_CACHING]
- .getStatusTest() == Common.IOP3_TC_STATUS_PROCESSING) {
- iopPhase3RunTestCaseCaching(1) */
} else {
Log.d(TAG, "do nothing")
}
@@ -2473,7 +3363,9 @@ class IOPTestActivity : AppCompatActivity() {
override fun onPhyRead(gatt: BluetoothGatt?, txPhy: Int, rxPhy: Int, status: Int) {
super.onPhyRead(gatt, txPhy, rxPhy, status) // TODO read PHY before starting throughput?
+ Log.d(TAG, "read PHY before starting throughput")
currentRxPhy = rxPhy
+ Log.d(TAG, "phy : " + currentRxPhy.toString())
}
override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {
@@ -2482,15 +3374,20 @@ class IOPTestActivity : AppCompatActivity() {
this@IOPTestActivity.mtu = mtu
mStartTimeDiscover = System.currentTimeMillis()
Log.d(TAG, "setPreferredPhy 1M")
- mBluetoothGatt?.setPreferredPhy(BluetoothDevice.PHY_LE_1M_MASK, BluetoothDevice.PHY_LE_1M_MASK, BluetoothDevice.PHY_OPTION_NO_PREFERRED)
- if (mIndexRunning == POSITION_TEST_DISCOVER_SERVICE || mIndexRunning == POSITION_TEST_IOP3_THROUGHPUT) {
+ mBluetoothGatt?.setPreferredPhy(
+ BluetoothDevice.PHY_LE_1M_MASK,
+ BluetoothDevice.PHY_LE_1M_MASK,
+ BluetoothDevice.PHY_OPTION_NO_PREFERRED
+ )
+ if (mIndexRunning == POSITION_TEST_DISCOVER_SERVICE || mIndexRunning == POSITION_TEST_IOP3_THROUGHPUT || mIndexRunning == POSITION_TEST_IOP3_LE_PRIVACY || (mIndexRunning == POSITION_TEST_IOP3_SECURITY && iopPhase3BondingStep > 2)) {
mListCharacteristics.clear()
characteristicsPhase3Security.clear()
characteristicIOPPhase3Control = null
refreshServices()
} else if ((mIndexRunning == POSITION_TEST_IOP3_OTA_WITHOUT_ACK
- || mIndexRunning == POSITION_TEST_IOP3_OTA_ACK)
- && !otaProcess) {
+ || mIndexRunning == POSITION_TEST_IOP3_OTA_ACK)
+ && !otaProcess
+ ) {
Log.d(TAG, "rediscover OTA")
handler?.postDelayed({
mListCharacteristics.clear()
@@ -2523,13 +3420,17 @@ class IOPTestActivity : AppCompatActivity() {
when (mIndexRunning) {
POSITION_TEST_SCANNER -> {
- if (device.name.equals(getSiliconLabsTestInfo().fwName, ignoreCase = true)) {
- mBluetoothDevice = device
- mDeviceAddress = device.address
- scanLeDevice(false)
- finishItemTest(POSITION_TEST_SCANNER, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_SCANNER])
- } else return
+ if (device.name.equals(getSiliconLabsTestInfo().fwName, ignoreCase = true)) {
+ mBluetoothDevice = device
+ mDeviceAddress = device.address
+ scanLeDevice(false)
+ finishItemTest(
+ POSITION_TEST_SCANNER,
+ getSiliconLabsTestInfo().listItemTest[POSITION_TEST_SCANNER]
+ )
+ } else return
}
+
POSITION_TEST_IOP3_OTA_ACK,
POSITION_TEST_IOP3_OTA_WITHOUT_ACK -> {
if (device.address == mDeviceAddress) {
@@ -2540,6 +3441,8 @@ class IOPTestActivity : AppCompatActivity() {
}, 5000)
} else return
}
+
+ POSITION_TEST_IOP3_LE_PRIVACY,
POSITION_TEST_IOP3_SECURITY,
POSITION_TEST_IOP3_CACHING -> {
if (device.address == mDeviceAddress) {
@@ -2586,7 +3489,8 @@ class IOPTestActivity : AppCompatActivity() {
/* Add IoP Test for P3 */
private const val POSITION_TEST_IOP3_THROUGHPUT = 6
private const val POSITION_TEST_IOP3_SECURITY = 7
- private const val POSITION_TEST_IOP3_CACHING = 8
+ private const val POSITION_TEST_IOP3_CACHING = 9
+ private const val POSITION_TEST_IOP3_LE_PRIVACY = 8
private const val POSITION_TEST_IOP3_OTA_ACK = 4
private const val POSITION_TEST_IOP3_OTA_WITHOUT_ACK = 5
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/DemoItemProvider.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/DemoItemProvider.kt
index c1a73571..bb604e32 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/DemoItemProvider.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/DemoItemProvider.kt
@@ -15,7 +15,7 @@ class DemoItemProvider {
add(ItemTestCaseInfo(6, "IOP Test OTA update without ACK", "Update user application via OTA without ACK.", null, Common.IOP3_TC_STATUS_WAITING))
add(ItemTestCaseInfo(7, "Throughput", "Throughput-GATT Notification.", null, Common.IOP3_TC_STATUS_WAITING))
add(ItemTestCaseInfo(8, "Security and Encryption", "Security and Encryption.", dataChildrenSecurity(), Common.IOP3_TC_STATUS_WAITING))
-
+ add(ItemTestCaseInfo(9, "LE Privacy", "LE Privacy.",null, Common.IOP3_TC_STATUS_WAITING))
/* This test should remain hidden for now due to investigation being underway. It may return later.
add(ItemTestCaseInfo(9, "GATT Caching", "GATT Caching.", dataChildrenCaching(), Common.IOP3_TC_STATUS_WAITING))
*/
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/SiliconLabsTestInfo.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/SiliconLabsTestInfo.kt
index 5327ece3..299bc1e7 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/SiliconLabsTestInfo.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/SiliconLabsTestInfo.kt
@@ -1,5 +1,7 @@
package com.siliconlabs.bledemo.features.iop_test.models
+import android.util.Log
+import com.siliconlabs.bledemo.features.iop_test.activities.IOPTestActivity
import com.siliconlabs.bledemo.features.iop_test.utils.Utils
import timber.log.Timber
import java.text.SimpleDateFormat
@@ -14,7 +16,7 @@ class SiliconLabsTestInfo(var fwName: String, val listItemTest: ArrayList 0) {
@@ -85,6 +88,7 @@ class SiliconLabsTestInfo(var fwName: String, val listItemTest: ArrayList append("7.1")
itemTest.idTest == 5 -> append("6.1")
itemTest.idTest == 6 -> append("6.2")
+ itemTest.idTest == 9 -> append("7.6")
else -> append(itemTest.idTest + 1)
}
append(",")
@@ -108,6 +112,13 @@ class SiliconLabsTestInfo(var fwName: String, val listItemTest: ArrayList {
+ ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2,
+ ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3 -> {
connectType = GattConnectType.BLINKY_THUNDERBOARD
cachedBoardType = characteristic.getStringValue(0)
gatt?.readCharacteristic(getPowerSourceCharacteristic(gatt))
@@ -125,6 +126,8 @@ class SelectDeviceDialog(
}
else -> {
+ showMessage(R.string.unknown_model)
+ (activity as MainActivity).dismissModalDialog()
Timber.d("Unknown model")
}
}
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 a465f107..f3b3546d 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
@@ -1,11 +1,19 @@
package com.siliconlabs.bledemo.home_screen.fragments
+import android.content.Context
import android.content.DialogInterface
import android.content.Intent
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.net.Uri
+import android.net.wifi.WifiManager
+import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Toast
+import androidx.core.content.ContextCompat.getColor
import androidx.recyclerview.widget.GridLayoutManager
import by.kirich1409.viewbindingdelegate.viewBinding
import com.siliconlabs.bledemo.R
@@ -13,6 +21,10 @@ import com.siliconlabs.bledemo.bluetooth.services.BluetoothService
import com.siliconlabs.bledemo.databinding.FragmentDemoBinding
import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoActivity
import com.siliconlabs.bledemo.features.demo.range_test.activities.RangeTestActivity
+import com.siliconlabs.bledemo.features.demo.wifi_ota_update.AlertErrorDialog
+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.home_screen.adapters.DemoAdapter
import com.siliconlabs.bledemo.home_screen.base.BaseServiceDependentMainMenuFragment
import com.siliconlabs.bledemo.home_screen.base.BluetoothDependent
@@ -26,9 +38,25 @@ import com.siliconlabs.bledemo.home_screen.menu_items.EslDemo
import com.siliconlabs.bledemo.home_screen.menu_items.HealthThermometer
import com.siliconlabs.bledemo.home_screen.menu_items.MatterDemo
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.WifiCommissioning
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.InputStream
+import java.net.InetAddress
+import java.net.ServerSocket
+import java.net.Socket
+import java.net.SocketTimeoutException
+import java.net.UnknownHostException
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+import java.util.Locale
+import java.util.Timer
+import java.util.TimerTask
class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoItemClickListener,
DialogInterface.OnDismissListener {
@@ -38,8 +66,22 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI
private val list: ArrayList = ArrayList()
private var selectDeviceDialog: SelectDeviceDialog? = null
+ private var otaProgressDialog: WiFiOtaProgressDialog? = null
+ private var otaFileSelectionDialog: WiFiOtaFileSelectionDialog? = null
+ private var otaFileManager: WiFiOtaFileManager? = null
+ private var otaFilePath: Uri? = null
+ private var socket : Socket? = null
+ private var serverSocket : ServerSocket? = null
+ private var portId = 8080
+ private var isClientConnected = false
+ private val kBits = "%.2f Kbit/s"
+ private var alertErrorDialog: AlertErrorDialog? = null
+ private var packetCount = 0
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ otaFileManager = WiFiOtaFileManager(requireContext())
+ initOtaProgressDialog()
list.apply {
add(
@@ -112,6 +154,13 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI
getString(R.string.matter_demo_description)
)
)
+ add(
+ OTADemo(
+ R.drawable.redesign_ic_demo_ota,
+ getString(R.string.ota_demo_title),
+ getString(R.string.ota_demo_desc)
+ )
+ )
}
}
@@ -185,6 +234,24 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI
requireContext().startActivity(Intent(requireContext(), MatterDemoActivity::class.java))
} else if (demoItem.connectType == BluetoothService.GattConnectType.RANGE_TEST) {
startActivity(Intent(requireContext(), RangeTestActivity::class.java))
+ } else if (demoItem.connectType == BluetoothService.GattConnectType.WIFI_OTA_UPDATE) {
+ if (isNetworkAvailable(context)) {
+ otaFileSelectionDialog = WiFiOtaFileSelectionDialog(object : WiFiOtaFileSelectionDialog.CancelCallback {
+ override fun onDismiss() {
+ otaFileSelectionDialog?.dismiss()
+ }},
+ listener = fileSelectionListener,
+ getLocalIpAddress()
+ ).also {
+ it.show(childFragmentManager, "ota_file_selection_dialog")
+ }
+ } else {
+ Toast.makeText(
+ requireContext(),
+ getString(R.string.turn_on_wifi),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
} else {
selectDeviceDialog = SelectDeviceDialog.newDialog(demoItem.connectType)
selectDeviceDialog?.show(childFragmentManager, "select_device_dialog")
@@ -194,4 +261,336 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI
override fun onDismiss(dialog: DialogInterface) {
selectDeviceDialog = null
}
+
+ @Throws(UnknownHostException::class)
+ private fun getLocalIpAddress(): String? {
+ val wifiManager =
+ (requireContext().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
+ }
+
+ 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
+ }
+ private val fileSelectionListener = object : WiFiOtaFileSelectionDialog.FileSelectionListener {
+ override fun onSelectFileButtonClicked() {
+ otaFileSelectionDialog?.disableUploadButton()
+ Intent(Intent.ACTION_GET_CONTENT)
+ .apply { type = "*/*" }
+ .also { startActivityForResult(Intent.createChooser(it,
+ getString(R.string.ota_choose_file)),
+ RPS_FILE_CHOICE_REQUEST_CODE
+ ) }
+ }
+
+ override fun onOtaButtonClicked() {
+ if(otaFileSelectionDialog?.checkPortNumberValid() == true){
+ otaFileManager?.otaFile?.let {
+ startOtaProcess()
+ } ?: if (otaFileManager?.otaFilename != null) {
+ Toast.makeText(requireContext(), getString(R.string.incorrect_file), Toast.LENGTH_SHORT).show()
+ } else {
+ Toast.makeText(requireContext(), getString(R.string.no_file_chosen), Toast.LENGTH_SHORT).show()
+ }
+ } else {
+ Toast.makeText(requireContext(), getString(R.string.port_id_validation), Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ override fun onCancelButtonClicked() {
+ otaFileSelectionDialog?.dismiss()
+ otaFileSelectionDialog = null
+ }
+ }
+
+ private fun initOtaProgressDialog() {
+ otaProgressDialog = WiFiOtaProgressDialog(requireContext())
+ initializeToDefaultValues()
+ otaProgressDialog?.btnOtaEnd?.setOnClickListener {
+ initializeToDefaultValues()
+ otaProgressDialog?.dismiss()
+ socket?.close()
+ serverSocket?.close()
+ }
+ otaProgressDialog?.btnCancel?.setOnClickListener {
+ initializeToDefaultValues()
+ otaProgressDialog?.dismiss()
+ socket?.close()
+ serverSocket?.close()
+ }
+ }
+
+ private fun initializeToDefaultValues() {
+ isClientConnected = false
+ otaProgressDialog?.progressBar?.progress = 0
+ otaProgressDialog?.dataRate?.visibility = View.INVISIBLE
+ otaProgressDialog?.dataSize?.text = getString(R.string.iop_test_n_percent, 0)
+ otaProgressDialog?.steps?.visibility = View.INVISIBLE
+ otaProgressDialog?.uploadImage?.visibility = View.VISIBLE
+// otaProgressDialog?.btnOtaEnd?.isEnabled = false
+ otaProgressDialog?.btnOtaEnd?.setBackgroundColor(getColor(requireContext(),R.color.silabs_red))
+ otaProgressDialog?.btnOtaEnd?.text = getString(R.string.button_cancel)
+ otaProgressDialog?.firmwareStatus?.text = getString(R.string.waiting_for_client_to_connect)
+ otaProgressDialog?.firmwareStatus?.setTextColor(getColor(requireContext(),R.color.silabs_dark_blue))
+ }
+
+ private fun showOtaProgressDialog() {
+ otaProgressDialog?.show()
+ }
+
+ private fun startOtaProcess() {
+ activity?.runOnUiThread {
+ showOtaProgressDialog()
+ portId = Integer.parseInt(otaFileSelectionDialog?.getPortId())
+ otaProgressDialog?.setProgressInfo(otaFileManager?.otaFilename, otaFileManager?.otaFile?.size, getLocalIpAddress() ,portId.toString())
+ animateLoading()
+
+ }
+ //Start OTA_data Upload in another thread
+ val otaUpload = Thread {
+
+ try {
+ serverSocket = ServerSocket(portId)
+ serverSocket?.receiveBufferSize = RECEIVER_BUFFER_SIZE
+// serverSocket.soTimeout = 60000
+ while (true) {
+ println("Waiting for client to connect")
+ socket = serverSocket?.accept()
+ println("Accept success")
+
+ Thread {
+ otaFilePath?.let {
+ getInputStreamFromUri(requireContext(), it)?.let {
+ processRequest(it)
+ }
+ }
+ socket?.close() //close socket
+ }.start()
+ }
+ } catch (e: SocketTimeoutException) {
+ showTimeOutError()
+ e.printStackTrace()
+ } catch (e: IOException) {
+ socket?.close()
+ serverSocket?.close()
+ e.printStackTrace()
+ }
+
+ }
+ otaUpload.start()
+ }
+
+ private fun showTimeOutAlertDialog() {
+ activity?.runOnUiThread {
+ alertErrorDialog = AlertErrorDialog( object : AlertErrorDialog.OtaErrorCallback {
+ override fun onDismiss() {
+ initializeToDefaultValues()
+ otaProgressDialog?.dismiss()
+ socket?.close()
+ serverSocket?.close()
+ }
+ })
+
+ alertErrorDialog?.show(childFragmentManager, "error_dialog")
+ }
+ }
+
+ private fun showTimeOutError() {
+ activity?.runOnUiThread {
+ if (!isClientConnected) {
+ otaProgressDialog?.firmwareStatus?.text = getString(R.string.server_timeout)
+ otaProgressDialog?.firmwareStatus?.setTextColor(
+ getColor(
+ requireContext(),
+ R.color.silabs_red
+ )
+ )
+// otaProgressDialog?.btnOtaEnd?.isEnabled = true
+ otaProgressDialog?.uploadImage?.visibility = View.GONE
+ }
+ }
+ }
+
+ private fun getInputStreamFromUri(context: Context, uri: Uri): FileInputStream? {
+ try {
+ val inputStream = context.contentResolver.openInputStream(uri)
+ if (inputStream != null) {
+ // Optionally, you may want to copy the content to a temporary file
+ // if you need a FileInputStream specifically
+ val tempFile = createTempFileFromInputStream(inputStream, context.cacheDir)
+ return FileInputStream(tempFile)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ return null
+ }
+
+ private fun createTempFileFromInputStream(inputStream: InputStream, cacheDir: File): File {
+ val tempFile = File.createTempFile("temp", null, cacheDir)
+ tempFile.deleteOnExit()
+ FileOutputStream(tempFile).use { fileOutputStream ->
+ inputStream.copyTo(fileOutputStream)
+ }
+ return tempFile
+ }
+
+ private fun processRequest(fp: FileInputStream): Int {
+ try {
+ println("processRequest")
+ var ctr = 0
+ var retLen: Int
+ val txLen = 0
+ val data = ByteArray(3)
+ val data1 = ByteArray(1503) // 1500 + 3
+ var cmdType: Byte
+ var length = 0
+ val outputStream = socket!!.getOutputStream()
+ val inputStream = socket!!.getInputStream()
+ val totalPackets = Integer.parseInt(otaFileManager?.otaFile?.size?.div(1024).toString())+1
+ while (true) {
+ retLen = inputStream.read(data, 0, 3)
+ if (retLen > 0) {
+ cmdType = data[0]
+ if (cmdType == RPS_HEADER) {
+ length = fp.read(data1, 3, 64)
+ data1[0] = RPS_HEADER
+ data1[1] = (length and 0xff).toByte()
+ data1[2] = (length shr 8 and 0xff).toByte()
+ fp.channel.position(0)
+ } else if (cmdType == RPS_DATA) {
+ length = fp.read(data1, 3, 1024)
+ data1[0] = RPS_DATA
+ data1[1] = (length and 0x00ff).toByte()
+ data1[2] = (length shr 8 and 0x00ff).toByte()
+ if (length == -1) {
+ fp.close()
+ outputStream.write(data1, 0, length + 3)
+ length = 0
+ data1[0] = RPS_DATA
+ data1[1] = (length and 0x00ff).toByte()
+ data1[2] = (length shr 8 and 0x00ff).toByte()
+ outputStream.write(data1, 0, length + 3)
+ outputStream.flush()
+ outputStream.close()
+ return ctr
+ }
+ }
+ } else if (length == 0) {
+ fp.close()
+ socket!!.close()
+ outputStream.write(data1, 0, length + 3)
+ return ctr
+ }
+ println("Size of data: $length")
+ outputStream.write(data1, 0, length + 3)
+ println("Send returns: $txLen")
+ if (txLen != 0) {
+ println("Error while sending")
+ return 0
+ }
+ //Update the Progress Dialog UI
+ updateProgressDialog(ctr++, totalPackets)
+ packetCount = ctr
+ if(ctr {
+ intent?.data?.let {
+ otaFilePath = it
+ otaFileManager?.readFilename(it)
+ otaFileSelectionDialog?.changeFileName(otaFileManager?.otaFilename)
+ if (otaFileManager?.hasCorrectFileExtensionRPS() == true) {
+ otaFileManager?.readFile(it).toString()
+ otaFileSelectionDialog?.enableUploadButton()
+ } else {
+ Toast.makeText(requireContext(), getString(R.string.incorrect_file), Toast.LENGTH_SHORT).show()
+ }
+ } ?: Toast.makeText(requireContext(), getString(R.string.chosen_file_not_found), Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ companion object {
+ private const val RECEIVER_BUFFER_SIZE = 2920
+ private const val RPS_FILE_CHOICE_REQUEST_CODE = 202
+ private const val RPS_HEADER: Byte = 0x01
+ private const val RPS_DATA: Byte = 0x00
+ }
}
\ No newline at end of file
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/SettingsFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/SettingsFragment.kt
index f02bfbc2..3f31e029 100644
--- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/SettingsFragment.kt
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/SettingsFragment.kt
@@ -104,12 +104,12 @@ class SettingsFragment : Fragment() {
}
companion object {
- private const val LINK_REPORT_ISSUE = "github.com/SiliconLabs/EFRConnect-android/issues"
+ private const val LINK_REPORT_ISSUE = "github.com/SiliconLabs/SimplicityConnect-android/issues"
private const val LINK_MORE_INFO = "silabs.com/products/wireless"
- private const val LINK_SOURCECODE = "github.com/SiliconLabs/EFRConnect-android"
- private const val LINK_USERS_GUIDE = "docs.silabs.com/bluetooth/latest/miscellaneous/mobile/efr-connect-mobile-app"
+ private const val LINK_SOURCECODE = "github.com/SiliconLabs/SimplicityConnect-android"
+ private const val LINK_USERS_GUIDE = "docs.silabs.com/mobile-apps/latest/mobile-apps-start/"
private const val LINK_SUPPORT = "silabs.com/support"
- private const val LINK_RELEASE_NOTES = "silabs.com/documents/public/release-notes/efr-connect-release-notes.pdf"
+ private const val LINK_RELEASE_NOTES = "docs.silabs.com/mobile-apps/latest/mobile-apps-release-notes/"
private const val LINK_DOCUMENTATION = "docs.silabs.com/bluetooth/latest"
private const val LINK_GOOGLE_PLAY_STORE = "play.google.com/store/apps/developer?id=Silicon+Laboratories"
}
diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/OTADemo.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/OTADemo.kt
new file mode 100644
index 00000000..ea3207d4
--- /dev/null
+++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/OTADemo.kt
@@ -0,0 +1,13 @@
+package com.siliconlabs.bledemo.home_screen.menu_items
+
+import androidx.annotation.DrawableRes
+import com.siliconlabs.bledemo.bluetooth.services.BluetoothService
+
+class OTADemo( @DrawableRes imageResId: Int,
+title: String,
+description: String
+) : DemoMenuItem(imageResId, title, description
+) {
+
+ override val connectType: BluetoothService.GattConnectType = BluetoothService.GattConnectType.WIFI_OTA_UPDATE
+}
\ No newline at end of file
diff --git a/mobile/src/main/res/drawable/background_grey_box.xml b/mobile/src/main/res/drawable/background_grey_box.xml
new file mode 100644
index 00000000..181e6dd7
--- /dev/null
+++ b/mobile/src/main/res/drawable/background_grey_box.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile/src/main/res/drawable/redesign_ic_demo_ota.xml b/mobile/src/main/res/drawable/redesign_ic_demo_ota.xml
new file mode 100644
index 00000000..9f86c388
--- /dev/null
+++ b/mobile/src/main/res/drawable/redesign_ic_demo_ota.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/si_connect.xml b/mobile/src/main/res/drawable/si_connect.xml
new file mode 100644
index 00000000..9e6c9751
--- /dev/null
+++ b/mobile/src/main/res/drawable/si_connect.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/si_connect_app_screen_background.jpg b/mobile/src/main/res/drawable/si_connect_app_screen_background.jpg
new file mode 100644
index 00000000..5e5372db
Binary files /dev/null and b/mobile/src/main/res/drawable/si_connect_app_screen_background.jpg differ
diff --git a/mobile/src/main/res/drawable/silabs_logo.xml b/mobile/src/main/res/drawable/silabs_logo.xml
new file mode 100644
index 00000000..aaece70d
--- /dev/null
+++ b/mobile/src/main/res/drawable/silabs_logo.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/drawable/wi_fi_symbol.png b/mobile/src/main/res/drawable/wi_fi_symbol.png
new file mode 100644
index 00000000..c9e32789
Binary files /dev/null and b/mobile/src/main/res/drawable/wi_fi_symbol.png differ
diff --git a/mobile/src/main/res/layout/dialog_alert_error.xml b/mobile/src/main/res/layout/dialog_alert_error.xml
new file mode 100644
index 00000000..d3f929dd
--- /dev/null
+++ b/mobile/src/main/res/layout/dialog_alert_error.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile/src/main/res/layout/dialog_device_info_layout.xml b/mobile/src/main/res/layout/dialog_device_info_layout.xml
index 62868561..74d3a332 100644
--- a/mobile/src/main/res/layout/dialog_device_info_layout.xml
+++ b/mobile/src/main/res/layout/dialog_device_info_layout.xml
@@ -1,67 +1,70 @@
+ android:orientation="vertical"
+ android:paddingTop="@dimen/matter_10dp"
+ android:paddingBottom="@dimen/matter_10dp">
+ android:textSize="17sp"
+ android:textStyle="bold"
+ tools:ignore="RtlHardcoded" />
+ android:layout_height="fill_parent"
+ android:background="@color/dialog_loading_spinner_start">
+
+ android:textColor="@color/black"
+ android:textSize="15sp"
+ android:textStyle="normal" />
+ android:padding="@dimen/matter_10dp">
+ android:textColor="@color/silabs_dark_blue"
+ android:textSize="12sp" />
+
-
+ android:textAllCaps="false"
+ android:textSize="12sp" />
-
\ No newline at end of file
diff --git a/mobile/src/main/res/layout/dialog_wifi_ota_file_update.xml b/mobile/src/main/res/layout/dialog_wifi_ota_file_update.xml
new file mode 100644
index 00000000..912c0dbb
--- /dev/null
+++ b/mobile/src/main/res/layout/dialog_wifi_ota_file_update.xml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile/src/main/res/layout/dialog_wifi_ota_progress.xml b/mobile/src/main/res/layout/dialog_wifi_ota_progress.xml
new file mode 100644
index 00000000..53b24611
--- /dev/null
+++ b/mobile/src/main/res/layout/dialog_wifi_ota_progress.xml
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/src/main/res/layout/si_connect_splash_screen.xml b/mobile/src/main/res/layout/si_connect_splash_screen.xml
new file mode 100644
index 00000000..8bd967b3
--- /dev/null
+++ b/mobile/src/main/res/layout/si_connect_splash_screen.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile/src/main/res/mipmap-anydpi/efr_redesign_launcher.xml b/mobile/src/main/res/mipmap-anydpi/efr_redesign_launcher.xml
deleted file mode 100644
index 84d0e911..00000000
--- a/mobile/src/main/res/mipmap-anydpi/efr_redesign_launcher.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/mobile/src/main/res/mipmap-anydpi/efr_redesign_launcher_round.xml b/mobile/src/main/res/mipmap-anydpi/efr_redesign_launcher_round.xml
deleted file mode 100644
index 84d0e911..00000000
--- a/mobile/src/main/res/mipmap-anydpi/efr_redesign_launcher_round.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/mobile/src/main/res/mipmap-hdpi/si_launcher.png b/mobile/src/main/res/mipmap-hdpi/si_launcher.png
new file mode 100644
index 00000000..1d8c592f
Binary files /dev/null and b/mobile/src/main/res/mipmap-hdpi/si_launcher.png differ
diff --git a/mobile/src/main/res/mipmap-hdpi/si_launcher_foreground.png b/mobile/src/main/res/mipmap-hdpi/si_launcher_foreground.png
new file mode 100644
index 00000000..fb71238c
Binary files /dev/null and b/mobile/src/main/res/mipmap-hdpi/si_launcher_foreground.png differ
diff --git a/mobile/src/main/res/mipmap-hdpi/si_launcher_round.png b/mobile/src/main/res/mipmap-hdpi/si_launcher_round.png
new file mode 100644
index 00000000..c7539176
Binary files /dev/null and b/mobile/src/main/res/mipmap-hdpi/si_launcher_round.png differ
diff --git a/mobile/src/main/res/mipmap-mdpi/si_launcher.png b/mobile/src/main/res/mipmap-mdpi/si_launcher.png
new file mode 100644
index 00000000..ffe6b1f1
Binary files /dev/null and b/mobile/src/main/res/mipmap-mdpi/si_launcher.png differ
diff --git a/mobile/src/main/res/mipmap-mdpi/si_launcher_foreground.png b/mobile/src/main/res/mipmap-mdpi/si_launcher_foreground.png
new file mode 100644
index 00000000..301bfc4a
Binary files /dev/null and b/mobile/src/main/res/mipmap-mdpi/si_launcher_foreground.png differ
diff --git a/mobile/src/main/res/mipmap-mdpi/si_launcher_round.png b/mobile/src/main/res/mipmap-mdpi/si_launcher_round.png
new file mode 100644
index 00000000..cd8b21fc
Binary files /dev/null and b/mobile/src/main/res/mipmap-mdpi/si_launcher_round.png differ
diff --git a/mobile/src/main/res/mipmap-xhdpi/si_launcher.png b/mobile/src/main/res/mipmap-xhdpi/si_launcher.png
new file mode 100644
index 00000000..b9a9ff04
Binary files /dev/null and b/mobile/src/main/res/mipmap-xhdpi/si_launcher.png differ
diff --git a/mobile/src/main/res/mipmap-xhdpi/si_launcher_foreground.png b/mobile/src/main/res/mipmap-xhdpi/si_launcher_foreground.png
new file mode 100644
index 00000000..c343a98d
Binary files /dev/null and b/mobile/src/main/res/mipmap-xhdpi/si_launcher_foreground.png differ
diff --git a/mobile/src/main/res/mipmap-xhdpi/si_launcher_round.png b/mobile/src/main/res/mipmap-xhdpi/si_launcher_round.png
new file mode 100644
index 00000000..59f1a322
Binary files /dev/null and b/mobile/src/main/res/mipmap-xhdpi/si_launcher_round.png differ
diff --git a/mobile/src/main/res/mipmap-xxhdpi/si_launcher.png b/mobile/src/main/res/mipmap-xxhdpi/si_launcher.png
new file mode 100644
index 00000000..695adde2
Binary files /dev/null and b/mobile/src/main/res/mipmap-xxhdpi/si_launcher.png differ
diff --git a/mobile/src/main/res/mipmap-xxhdpi/si_launcher_foreground.png b/mobile/src/main/res/mipmap-xxhdpi/si_launcher_foreground.png
new file mode 100644
index 00000000..a4965086
Binary files /dev/null and b/mobile/src/main/res/mipmap-xxhdpi/si_launcher_foreground.png differ
diff --git a/mobile/src/main/res/mipmap-xxhdpi/si_launcher_round.png b/mobile/src/main/res/mipmap-xxhdpi/si_launcher_round.png
new file mode 100644
index 00000000..e16229c0
Binary files /dev/null and b/mobile/src/main/res/mipmap-xxhdpi/si_launcher_round.png differ
diff --git a/mobile/src/main/res/mipmap-xxxhdpi/si_launcher.png b/mobile/src/main/res/mipmap-xxxhdpi/si_launcher.png
new file mode 100644
index 00000000..58c4151e
Binary files /dev/null and b/mobile/src/main/res/mipmap-xxxhdpi/si_launcher.png differ
diff --git a/mobile/src/main/res/mipmap-xxxhdpi/si_launcher_foreground.png b/mobile/src/main/res/mipmap-xxxhdpi/si_launcher_foreground.png
new file mode 100644
index 00000000..44a8d78d
Binary files /dev/null and b/mobile/src/main/res/mipmap-xxxhdpi/si_launcher_foreground.png differ
diff --git a/mobile/src/main/res/mipmap-xxxhdpi/si_launcher_round.png b/mobile/src/main/res/mipmap-xxxhdpi/si_launcher_round.png
new file mode 100644
index 00000000..028a200b
Binary files /dev/null and b/mobile/src/main/res/mipmap-xxxhdpi/si_launcher_round.png differ
diff --git a/mobile/src/main/res/values-v31/styles.xml b/mobile/src/main/res/values-v31/styles.xml
index 8662c264..4bb651ec 100644
--- a/mobile/src/main/res/values-v31/styles.xml
+++ b/mobile/src/main/res/values-v31/styles.xml
@@ -2,7 +2,7 @@
diff --git a/mobile/src/main/res/values/colors.xml b/mobile/src/main/res/values/colors.xml
index ec133aba..9271afd4 100644
--- a/mobile/src/main/res/values/colors.xml
+++ b/mobile/src/main/res/values/colors.xml
@@ -11,6 +11,7 @@
#00000000
#F9C80E
#7A7878
+ #14A359
#400086D9
diff --git a/mobile/src/main/res/values/dimens.xml b/mobile/src/main/res/values/dimens.xml
index 6adc4908..b8195d0d 100644
--- a/mobile/src/main/res/values/dimens.xml
+++ b/mobile/src/main/res/values/dimens.xml
@@ -321,4 +321,9 @@
380dp
200dp
10dp
+
+
+ 240dp
+ -40dp
+ 40dp
diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml
index a8a4e784..fc31d24f 100644
--- a/mobile/src/main/res/values/strings.xml
+++ b/mobile/src/main/res/values/strings.xml
@@ -1,7 +1,7 @@
- EFR Connect
+ Si Connect
Bluetooth adapter disabled
@@ -94,6 +94,7 @@
running \"%s\" firmware."
Please connect a device
Reading board type…
+ Failed to discover services
Menu title
@@ -234,7 +235,7 @@
For more information visit:
Source code:
- EFR Connect User\'s Guide:
+ Simplicity Connect User\'s Guide:
Support:
Release notes:
Additional documentation:
@@ -336,6 +337,7 @@
Unknown
+ Unknown Model
Hex
ASCII
Decimal
@@ -1148,7 +1150,7 @@
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.
+ Password must be minimum 8 characters.BT
Add the device name. This is the name that will be used to reference this device.
Add Device Name
Manual QR code payload ID:
@@ -1159,5 +1161,26 @@
Please enter valid device name
Start Commissioning
QR Code info
- Failed to discover services
+
+ //Wi-Fi OTA Firmware Update Demo
+ Wi-Fi OTA Update
+ 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.
+ IP Address:
+ Server Port:
+ Select firmware file for updating SiWx91x
+ Select *.rps file
+ %d OF %d
+ Configure Wi-Fi OTA Server
+ Select file:
+ Turn ON your Wi-Fi connection
+ Waiting for client to connect
+ Firmware update in progress.
+ Firmware updated successfully!
+ Exceeded timeout! Please try again
+ Enter 4 digit valid Server PORT
+ Done
+ Update
+ Updating Firmware
+ Alert
+ QR Code Info
diff --git a/mobile/src/main/res/values/styles.xml b/mobile/src/main/res/values/styles.xml
index 84f70a48..9be10c15 100644
--- a/mobile/src/main/res/values/styles.xml
+++ b/mobile/src/main/res/values/styles.xml
@@ -14,7 +14,7 @@
@@ -353,6 +353,13 @@
- false
+
+