androidestimoteindoor-positioning-systemuwb

Does Estimote UWB SDK for Android works with multiple Estimote UWB Beacons?


I'm currently working on an Android application that does indoor wayfinding.

I bought three Estimote UWB beacons and their Android UWB SDK that do not have any documentation whatsoever.

I settled up the main activity to check if the SDK is working correctly, here is the code:

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        FindYourWayTheme {
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = MaterialTheme.colorScheme.background
            ) {

            }
        }
    }

    setContentView(R.layout.login)

    val usernameEditText = findViewById<EditText>(R.id.username)
    val passwordEditText = findViewById<EditText>(R.id.password)
    val loginButton = findViewById<Button>(R.id.loginbtn)

    loginButton.setOnClickListener {
        CoroutineScope(Dispatchers.Main).launch {
            val username = usernameEditText.text.toString()
            val password = passwordEditText.text.toString()

            val encryptedUsername = encryptWithPublicKey(username, publicKeyPEM)
            val encryptedPassword = encryptWithPublicKey(password, publicKeyPEM)

           sendSignInCredentialsToLambda(encryptedUsername, encryptedPassword, applicationContext)
        }
    }

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, Manifest.permission.UWB_RANGING) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.UWB_RANGING), 1)
    } else {
        startUWBScanning()
    }
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 1 && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
    } else {
        Log.d("PERMISSIONS", "Some permissions are denied")
    }
}

private fun startUWBScanning() {
    val uwbManager = EstimoteUWBFactory.create()
    val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
    val deviceAddress = "D8:EB:87:DF:E7:BE"
    val deviceAddress1 = "EC:01:7C:7F:67:50"
    val device: BluetoothDevice? = bluetoothAdapter?.getRemoteDevice(deviceAddress)
    val device1: BluetoothDevice? = bluetoothAdapter?.getRemoteDevice(deviceAddress1)

    uwbManager.init(this, this) { deniedRequirements ->
        deniedRequirements.forEach {
            Log.d("UWBInit", "Requirement denied: $it")
        }
    }
    if (device != null && device1 != null) {
        launchUWBConnection(uwbManager, device)
        launchUWBConnection(uwbManager, device1)
    } else {
        Log.d("NotFoundBT", "DUCK OFF")
    }
    uwbManager.stopDeviceScanning()
}

fun launchUWBConnection(uwbManager: EstimoteUWBManager, device: BluetoothDevice) {
    CoroutineScope(Dispatchers.Main.immediate).launch {
        uwbManager.connect(device, applicationContext)
        uwbManager.startDeviceScanning(applicationContext)
        uwbManager.rangingResult.collect { result ->
            when (result) {
                is EstimoteUWBRangingResult.Position -> {
                    val position = result.position

                    // Extract position information
                    val positionInfo =
                        "Position of ${result.device.address} : Distance=${position.distance?.value}, Azimuth=${position.azimuth?.value}, Elevation=${position.elevation?.value}"

                    // Log or print the information
                    Log.d("UWBResult", positionInfo)
                }

                else -> {
                    // Handle other types of EstimoteUWBRangingResult
                }
            }
        }
    }
}

fun onRegisterClick(view: View) {
    val intent = Intent(this, SignUpActivity::class.java)
    startActivity(intent)
}
}

Now, the issue is that when I try to connect to one device the position (and all the data) looks fine, this is a sample log:

Position of 7B:ED : Distance=0.14999998, Azimuth=null, Elevation=null

Though, when I try to connect a second UWB beacon I receive this error message:

Creating Gms Client session scope

Error when removing Please check that the ranging is active and theranging profile supports multi-device ranging.

RangingResultPeerDisconnected address:20:00

I don't know if there's an issue with my code, or maybe with the SDK itself. Also I could not find any reference in the android uwb library documentation, that says if an android phone (in my case a Pixel 7 Pro) can connect to multiple devices via UWB.


Solution

  • Estimote does not provide any support more than a basic SDK, without any documentation.

    After some months their support team answered that there was no official support for multiple beacons in Android, becoming a useless product both for iOS (which already has AirTag) and Android.