Closed ahmadshoh-orc closed 2 months ago
Hello, We are quite busy with other projects at the moment. We will come back to you as soon as possible. Sorry!
Hello,
I wanted to share my latest observations and compile all my problems and questions together briefly.
QUESTION: Is it correct just call "connect" function from Ble-Library for reconnection?
bleManager.connect(address) {
Log.d("QBleMesh", "Connected to device with address: $address")
handler.postDelayed({
Log.d("QBleMesh", "Starting configuration process.")
startConfigurationProcess(selectedPeripheral, unicastAddress, callback)
}, 5000)
}
Details of my attempts:
3.1. I attempted to call the connect function directly. It reconnects to the node, fetches new services and characteristics, and I can send ConfigAppKeyAdd
and ConfigCompositionDataGet
. Mesh messages are processed, but the problem is that no response messages are received, as seen in the logs.
3.2. I tried manually disconnecting from the provisioned node first and then reconnecting. It reconnects, but the "done" callback is not called, so I cannot start the configuration process.
bleManager.disconnect().enqueue()
bleManager.connect(address) {
// Configuration
}
I have no ideas at all about what the problem might be and how to solve it. I would appreciate any insights or suggestions on how to resolve it. Thank you!
Hello,
When it comes to connecting to a mesh node we don't use the concept of connecting using a address. Oncea node is provisioned, it belongs to a mesh network and all devices in the network advertises with a certain network id derived using the primary network key that was added during provisioning. When connecting to a provisioned mesh node or the proxy node you have to always filter the devices using their network ID. May be you have this already in place, however an example of how to implement could be found in the sample app.
D/BluetoothGatt(13013): setCharacteristicNotification() - uuid: 00002ade-0000-1000-8000-00805f9b34fb enable: true D/BluetoothGatt(13013): setCharacteristicNotification() - uuid: 00002adc-0000-1000-8000-00805f9b34fb enable: true
According to your logs I see the second characteristic seems to be wrong.
Following are the characteristics for a mesh proxy node with the mesh proxy service. https://github.com/NordicSemiconductor/Android-nRF-Mesh-Library/blob/162a29e1b9b9de4c15f39f11c9034d51f486b1bd/app/src/main/java/no/nordicsemi/android/nrfmesh/ble/BleMeshManager.java#L66-L71
Let me know how this goes.
Hello Roshanrajaratman,
Thank you for your response. I implemented the reconnection method as you suggested. However, the logs indicate that the correct characteristics are initially set, but then overwritten by the provisioning characteristics. I am unsure why this occurs. I debugged each step, but I do not see any point in the code where the provisioning characteristics are being set after reconnection.
Here are the relevant log entries:
V/MeshManagerApi(18345): Received provisioning message: 0x0308
D/BleMeshManager(18345): provisioning is complete. unicast address is -> 2
D/BleMeshManager(18345): we did it.
D/BluetoothGatt(18345): onServiceChanged() - Device=XX:XX:XX:XX:08:92
D/BluetoothGatt(18345): cancelOpen() - device: 7C:DF:A1:DB:08:92
D/BluetoothGatt(18345): discoverServices() - device: 7C:DF:A1:DB:08:92
D/BluetoothGatt(18345): onClientConnectionState() - status=0 clientIf=6 device=XX:XX:XX:XX:08:92
D/BluetoothGatt(18345): close()
D/BluetoothGatt(18345): unregisterApp() - mClientIf=6
D/BluetoothAdapter(18345): getBleEnabledArray(): ON
D/BluetoothAdapter(18345): getBleEnabledArray(): ON
D/BluetoothAdapter(18345): semIsBleEnabled(): ON
D/BluetoothAdapter(18345): getBleEnabledArray(): ON
D/BluetoothLeScanner(18345): Start Scan with callback
D/BluetoothLeScanner(18345): onScannerRegistered() - status=0 scannerId=9 mScannerId=0
D/BluetoothAdapter(18345): getBleEnabledArray(): ON
D/BluetoothAdapter(18345): getBleEnabledArray(): ON
D/BluetoothLeScanner(18345): Stop Scan with callback
D/BluetoothAdapter(18345): getBleEnabledArray(): ON
D/BluetoothGatt(18345): connect() - device: 7C:DF:A1:DB:08:92, auto: false
D/BluetoothGatt(18345): registerApp()
D/BluetoothGatt(18345): registerApp() - UUID=d2a73192-1369-4fda-ad16-f8a0b2535a85
D/BluetoothGatt(18345): onClientRegistered() - status=0 clientIf=6
D/BluetoothAdapter(18345): getBleEnabledArray(): ON
D/BluetoothGatt(18345): onClientConnectionState() - status=0 clientIf=6 device=XX:XX:XX:XX:08:92
D/BluetoothGatt(18345): discoverServices() - device: 7C:DF:A1:DB:08:92
D/BluetoothGatt(18345): onConnectionUpdated() - Device=XX:XX:XX:XX:08:92 interval=6 latency=0 timeout=500 status=0
D/BluetoothGatt(18345): onSearchComplete() = Device=XX:XX:XX:XX:08:92 Status=0
D/BluetoothGatt(18345): configureMTU() - device: 7C:DF:A1:DB:08:92 mtu: 517
D/BluetoothGatt(18345): onConfigureMTU() - Device=XX:XX:XX:XX:08:92 mtu=23 status=0
D/BluetoothGatt(18345): setCharacteristicNotification() - uuid: 00002ade-0000-1000-8000-00805f9b34fb enable: true
D/BleMeshManager(18345): Data received -> mtu: 20, pdu: [65, 1, 0, -120, -30, -73, 36, 123, -105, -71, 90, 0, 0, 0, 0, 43, 69, 23, 29, -67]
D/BluetoothGatt(18345): setCharacteristicNotification() - uuid: 00002adc-0000-1000-8000-00805f9b34fb enable: true
D/BleMeshManager(18345): Data received -> mtu: 20, pdu: [-63, 110, 69, 122]
D/MeshManagerApi(18345): Received mesh beacon: SecureNetworkBeacon { KeyRefreshActive: false, IV Index: IV Index: 0, IV Update Active: false, Authentication Value: 0x2B45171DBD6E457A}
D/MeshManagerApi(18345): Secure Network Beacon authenticated.
D/MeshManagerApi(18345): Last IV Index: 0
I/MeshManagerApi(18345): Setting IV Update Active to: false
D/BluetoothGatt(18345): onConnectionUpdated() - Device=XX:XX:XX:XX:08:92 interval=24 latency=0 timeout=500 status=0
Below is the implementation of the connection to the provisioned node after provisioning:
fun provision(address: String, callback: (provisionedNode: ProvisionedNode) -> Unit) {
provisioningService.provisionCallback = { selectedPeripheral, provisionedMeshNodeNode, unicastAddress ->
val pnScanner = ProvisionedDevicesScanner(activity, meshManagerApi, bleManager)
pnScanner.provisionedMeshNode = provisionedMeshNodeNode
pnScanner.connectionCallback = SuccessCallback {
Log.d("QBleMesh", "Connection callback was called.")
startConfigurationProcess(selectedPeripheral, unicastAddress, callback)
}
bleManager.disconnect().enqueue()
handler.postDelayed({ pnScanner.open() }, 2000)
}
val unprovisionedScanResult = unprovisionedScanResults.firstOrNull { it.device.address == address }
unprovisionedScanResult?.let { result ->
bleManager.connect(address) {
Log.d("QBleMesh", "Connection done was called.")
provisioningService.startProvisioningProcess(result)
}
}
}
Here is the ProvisionedDevicesScanner
class:
class ProvisionedDevicesScanner(
private val activity: Activity,
private val meshManagerApi: MeshManagerApi,
private val bleManager: BleMeshManager
) : ScanCallback() {
private var isStarted: Boolean = false
var connectionCallback: SuccessCallback? = null
private var _provisionedMeshNode: ProvisionedMeshNode? = null
var provisionedMeshNode: ProvisionedMeshNode
get() = _provisionedMeshNode ?: throw IllegalStateException("ProvisionedMeshNode is not set")
set(value) {
_provisionedMeshNode = value
}
override fun onScanResult(callbackType: Int, result: ScanResult) {
result.scanRecord?.getServiceData(ParcelUuid(BleMeshManager.MESH_PROXY_UUID))?.let { serviceData ->
if (meshManagerApi.isAdvertisedWithNodeIdentity(serviceData) && meshManagerApi.nodeIdentityMatches(provisionedMeshNode, serviceData)) {
stopScan()
bleManager.connect(result.device).done(connectionCallback!!).retry(3, 500).enqueue()
}
}
}
fun open() {
if (!isStarted) {
PermissionManager.informAboutPermissionsGranted(activity) {
startScan()
}
}
}
private fun startScan(): Boolean {
if (isStarted) return true
val scanSettings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setReportDelay(0)
.setUseHardwareFilteringIfSupported(false)
.build()
val scanFilters = listOf(
ScanFilter.Builder().setServiceUuid(ParcelUuid(BleMeshManager.MESH_PROXY_UUID)).build()
)
return try {
BluetoothLeScannerCompat.getScanner().startScan(scanFilters, scanSettings, this)
isStarted = true
true
} catch (e: IllegalArgumentException) {
isStarted = false
false
}
}
private fun stopScan(): Boolean {
if (!isStarted) return true
return try {
BluetoothLeScannerCompat.getScanner().stopScan(this)
isStarted = false
true
} catch (error: Exception) {
false
}
}
}
Could you please help me understand why the characteristics are being overwritten and how to fix this issue?
Thank you!
I found the error. After disconnecting, I needed to first clear all characteristics in BleMeshManager
and then reconnect to it. After adding this code, everything now works fine.
fun clearCharacteristics() {
// Clear all cached characteristics and reset GATT instance
meshProvisioningDataInCharacteristic = null
meshProvisioningDataOutCharacteristic = null
meshProxyDataInCharacteristic = null
meshProxyDataOutCharacteristic = null
gatt = null
}
Edited (28.06.2024)
I am implementing device provisioning and configuration using the NordicMesh library for Android. The project is built with Flutter, utilizing a native Kotlin plugin. While the provisioning process executes correctly, I'm encountering issues during the configuration phase. Specifically, after reconnection, I receive no response for the ConfigAppKeyAdd and ConfigCompositionDataGet messages. The logs indicate that the MeshMessage was processed, but no further messages are received.
Could someone help identify what might be wrong in my code or what I might be missing?
Code
Here is the relevant code for provisioning and configuration:
Output Logs
Here are the relevant output logs during the provisioning process: