Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
4468bd0
Remove nRF prefix
roshanrajaratnam Dec 6, 2025
f550006
Use application keys size when adding a new one
roshanrajaratnam Dec 6, 2025
f03c178
Fix modifiers
roshanrajaratnam Dec 7, 2025
48039cf
Fix constructor
roshanrajaratnam Dec 7, 2025
65e2340
Improve documentation
roshanrajaratnam Dec 10, 2025
17b5cde
Adds a unique ID property that can be used in lazycolumns
roshanrajaratnam Dec 10, 2025
64f4e8a
Fix dependencies
roshanrajaratnam Dec 10, 2025
1cadb04
Fixes an issue with the key row getting recomposed when swiping tio d…
roshanrajaratnam Dec 10, 2025
83bf0ec
Clear current snackbarData before showing new and improves the messaging
roshanrajaratnam Dec 11, 2025
dc19172
Fixes a bug where localNode was not being excluded when checking if t…
roshanrajaratnam Dec 11, 2025
7a0ee18
Call onSwipe from a coroutineScope
roshanrajaratnam Dec 11, 2025
96b2732
Clean up
roshanrajaratnam Dec 11, 2025
474d3a9
Improvements to swipe to delete keys in the network keys list
roshanrajaratnam Dec 11, 2025
aece90d
Clean up
roshanrajaratnam Dec 12, 2025
b64d222
Adds an api to remove a provisioner with a given UUID
roshanrajaratnam Dec 12, 2025
8d1afa9
Migrates to the new SwipeToDismissBox
roshanrajaratnam Dec 12, 2025
49af16c
Add 0x prefix to maintain ui consistency
roshanrajaratnam Dec 15, 2025
75178c0
Filter out the items that are marked for deletion
roshanrajaratnam Dec 15, 2025
1c5de25
Use unique ID
roshanrajaratnam Dec 15, 2025
2680d36
Use scene api to return a scene
roshanrajaratnam Dec 15, 2025
d73f682
Clean up
roshanrajaratnam Dec 15, 2025
736f7d9
Minor clean up
roshanrajaratnam Dec 15, 2025
bd1c48e
Adds an API to remove a scene with a given scene number
roshanrajaratnam Dec 15, 2025
a6a35b0
make internal
roshanrajaratnam Dec 15, 2025
7c5499f
Introduces a new api to add a Scene to a network with a given name fo…
roshanrajaratnam Dec 15, 2025
9ca1883
Remove default value
roshanrajaratnam Dec 15, 2025
12f32ba
Adds new exception class
roshanrajaratnam Dec 15, 2025
a0f2bec
Migrates scenes ui to SwipeToDismissBox
roshanrajaratnam Dec 15, 2025
c149da1
Use stateflow update
roshanrajaratnam Dec 15, 2025
77053c7
Minor improvements to keep the ui implementation consistent between A…
roshanrajaratnam Dec 15, 2025
8526640
Move selected scene in to the viewmodel
roshanrajaratnam Dec 15, 2025
426f357
Clean up
roshanrajaratnam Dec 15, 2025
1b30826
Move selectedKeyIndex to the viewmodel
roshanrajaratnam Dec 15, 2025
06922c2
fix import
roshanrajaratnam Dec 15, 2025
8f98dd7
Move selected key index to the view model
roshanrajaratnam Dec 15, 2025
cc3dc8c
Move selected provisioner uuid to the view model
roshanrajaratnam Dec 16, 2025
ea55457
Let's not add AllNodes to the _subscribe list as this property gets s…
roshanrajaratnam Dec 16, 2025
fffab9a
Migrate to swipe to dismiss box
roshanrajaratnam Dec 16, 2025
469a5a9
Remove debug log
roshanrajaratnam Dec 16, 2025
70562f0
Migrate to SwipeToDismissBox
roshanrajaratnam Dec 16, 2025
58a1faf
Clean up
roshanrajaratnam Dec 16, 2025
ea9b13f
Fixes a bug where the proxy filter list does not get updated.
roshanrajaratnam Dec 16, 2025
ec2eb84
Migrates to SwipeToDismissBox
roshanrajaratnam Dec 17, 2025
6367f36
Migrates to SwipeToDismissBox
roshanrajaratnam Dec 17, 2025
da0f179
Add icon under swipe to dismiss box
roshanrajaratnam Dec 17, 2025
0d19038
Base element name on the elements size
roshanrajaratnam Dec 17, 2025
ea99904
Remove unused common composable
roshanrajaratnam Dec 17, 2025
f904031
Make bound network key index internal
roshanrajaratnam Dec 17, 2025
153fb04
ApplicationKey in use should just check if its added to a node.
roshanrajaratnam Dec 17, 2025
7ef3100
NetworkKey in use should just check if its added to a node or its in …
roshanrajaratnam Dec 17, 2025
cff90cf
Use network key to access the bound key index
roshanrajaratnam Dec 17, 2025
1582721
Use bind app key to network key
roshanrajaratnam Dec 17, 2025
2addbbc
Make icon button mandatory
roshanrajaratnam Dec 17, 2025
2c0ea83
Specifying application keys size
roshanrajaratnam Dec 17, 2025
8f65d8f
Fix imports
roshanrajaratnam Dec 17, 2025
f85afaa
Virtual address should not be a heartbeat subscription destination
roshanrajaratnam Dec 18, 2025
7821e1f
Display only other nodes as heartbeat subscription sources
roshanrajaratnam Dec 18, 2025
5489e42
Fix include model
roshanrajaratnam Dec 18, 2025
b16eaa3
Make primary element not nullable
roshanrajaratnam Dec 18, 2025
3317084
Improvements to heartbeat ui
roshanrajaratnam Dec 18, 2025
454611f
Fixes a possible nullpointer when sending a heartbeat sub and pub mes…
roshanrajaratnam Dec 18, 2025
1e4695e
UI improvements
roshanrajaratnam Dec 18, 2025
fff6ff2
onValueChanged now validates the value based on the given RegEx
roshanrajaratnam Dec 18, 2025
4cdb7a7
Fix RegEx to limit inputs
roshanrajaratnam Dec 18, 2025
3f355b0
Fix strings
roshanrajaratnam Dec 18, 2025
203e7bc
Fix regex to limit inputs
roshanrajaratnam Dec 18, 2025
893c0c1
Fix regex to limit inputs
roshanrajaratnam Dec 18, 2025
782e781
Clean up
roshanrajaratnam Dec 18, 2025
7a6595d
The bearer will now wait until the MTU configuration is completed
roshanrajaratnam Dec 18, 2025
db90ef0
Fix regex
roshanrajaratnam Dec 18, 2025
3c052c5
Fixes an issue where current value gets cleared upon adding a provisi…
roshanrajaratnam Dec 18, 2025
f4526f7
Reorder Check and Unassign buttons
roshanrajaratnam Dec 18, 2025
b457f1e
Reuse snackbarHostState
roshanrajaratnam Dec 18, 2025
6f1a6ec
Fix dropdown tiem
roshanrajaratnam Dec 18, 2025
a5672bc
We should allow removing a node even though a message might be in pro…
roshanrajaratnam Dec 18, 2025
2b02f1a
Fix dropdown
roshanrajaratnam Dec 18, 2025
a98c0ae
Pass the overlapping regions for coloring
roshanrajaratnam Dec 18, 2025
602fc5f
Improvements to Ranges Screen
roshanrajaratnam Dec 18, 2025
e8b7ae9
Improvements to heartbeat drop downs
roshanrajaratnam Dec 18, 2025
99eb6fe
Apply tint for icons
roshanrajaratnam Dec 18, 2025
fc0d0af
Remove unused viewmodels
roshanrajaratnam Dec 19, 2025
12307e5
Refactor
roshanrajaratnam Dec 19, 2025
65acbdd
Move ranges to provisioners module
roshanrajaratnam Dec 19, 2025
3fe8df7
Remove ranges module
roshanrajaratnam Dec 19, 2025
c015e34
Fix strings
roshanrajaratnam Dec 19, 2025
5e9acfc
Fix placeholder
roshanrajaratnam Dec 19, 2025
b8e386c
bump version catalog
roshanrajaratnam Dec 19, 2025
252563b
Disable minifying the library
roshanrajaratnam Dec 19, 2025
03ba69c
Fix imports
roshanrajaratnam Dec 19, 2025
4801db9
Use nordic scanner device item
roshanrajaratnam Dec 19, 2025
ec202f4
Apply icon tint
roshanrajaratnam Dec 19, 2025
22aa6d0
Fixes class cast when filtering HeartbeatSubscriptionDestinations
roshanrajaratnam Dec 19, 2025
af379ca
don't throw here
roshanrajaratnam Dec 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ dependencies {
implementation(project(":feature:application-keys"))
implementation(project(":feature:scenes"))
implementation(project(":feature:provisioners"))
implementation(project(":feature:ranges"))
implementation(project(":feature:export"))
implementation(project(":mesh:core"))
implementation(project(":mesh:provisioning"))
Expand Down
4 changes: 3 additions & 1 deletion app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class no.nordicsemi.android.nrfmesh.core.navigation.ClickableSetting { *; }
-keep class no.nordicsemi.android.nrfmesh.core.navigation.ClickableSetting { *; }
-keep class no.nordicsemi.kotlin.mesh.** { *; }
-dontwarn no.nordicsemi.kotlin.mesh.**
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ fun NetworkRoute(
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Characters
),
regex = Regex("[0-9A-Fa-f]{0,4}"),
regex = Regex("^[0-9A-Fa-f]{0,4}$"),
isError = isError,
)
Row(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ import no.nordicsemi.kotlin.mesh.core.exception.SceneInUse
import no.nordicsemi.kotlin.mesh.core.exception.SecurityException
import no.nordicsemi.kotlin.mesh.core.layers.access.AccessError
import no.nordicsemi.kotlin.mesh.logger.LogLevel
import kotlin.concurrent.atomics.AtomicLong
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import kotlin.concurrent.atomics.incrementAndFetch

/**
* Helper object containing utility methods.
Expand Down Expand Up @@ -127,3 +130,15 @@ fun copyToClipboard(
clipboard.setClipEntry(clipEntry = ClipEntry(clipData = clip))
}
}

object KeyIdGenerator {
@OptIn(ExperimentalAtomicApi::class)
private val counter = AtomicLong(0)

/**
* Generates the next unique ID. This is a helper method used to generate unique IDs for keys in
* a LazyColumn
*/
@OptIn(ExperimentalAtomicApi::class)
fun nextId() = counter.incrementAndFetch()
}
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ class CoreDataRepository @Inject constructor(
* @param boundNetworkKey Bound Network Key
*/
fun addApplicationKey(
name: String = "Application Key ${meshNetwork.applicationKeys.size}",
name: String = "Application Key ${meshNetwork.applicationKeys.size + 1}",
boundNetworkKey: NetworkKey,
): ApplicationKey = meshNetwork.add(
name = name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ class AndroidGattBearer(
peripheral = peripheral
) {
@OptIn(ExperimentalUuidApi::class)
override suspend fun open() {
super.open()
override suspend fun configurePeripheral(peripheral: Peripheral) {
// Request highest connection parameters after connect in the super.open()
peripheral.requestHighestValueLength()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class AndroidPbGattBearer(
peripheral = peripheral
) {
@OptIn(ExperimentalUuidApi::class)
override suspend fun open() {
super.open()
override suspend fun configurePeripheral(peripheral: Peripheral) {
// Request highest connection parameters after connect in the super.open()
peripheral.requestHighestValueLength()

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,44 @@

package no.nordicsemi.android.nrfmesh.core.data.models

import no.nordicsemi.android.nrfmesh.core.common.KeyIdGenerator
import no.nordicsemi.kotlin.mesh.core.model.ApplicationKey
import no.nordicsemi.kotlin.mesh.core.model.KeyIndex
import no.nordicsemi.kotlin.mesh.core.model.NetworkKey
import kotlin.uuid.ExperimentalUuidApi

/**
* Application Keys are used to secure communications at the upper transport layer.
* The application key (AppKey) shall be generated using a random number generator
* compatible with the requirements in Volume 2, Part H, Section 2 of the Core Specification [1].
*
* @property index The index property contains an integer from 0 to 4095 that
* represents the NetKey index for this network key.
* @property name Human-readable name for the application functionality associated
* with this application key.
* @property boundNetKeyIndex The boundNetKey property contains a corresponding Network Key index
* of the network key in the mesh network.
* @property index The index property contains an integer from 0 to 4095 that
* represents the NetKey index for this network key.
* @property key 128-bit application key.
* @property oldKey OldKey property contains the previous application key.
* @property boundNetworkKey Network key to which this application key is bound to.
* @param key 128-bit application key.
* @property boundNetKeyIndex The boundNetKey property contains a corresponding Network Key index
* of the network key in the mesh network.
* @property isInUse True if the application key is currently in use in the mesh network.
*/
@OptIn(ExperimentalUuidApi::class)
data class ApplicationKeyData(
val name: String,
val index: KeyIndex,
val key: ByteArray,
val oldKey: ByteArray? = null,
val boundNetKeyIndex: KeyIndex,
val boundNetworkKey: NetworkKey?,
val isInUse: Boolean
val boundNetworkKeyName: String,
val isInUse: Boolean,
val id: Long = KeyIdGenerator.nextId()
) {
constructor(key: ApplicationKey) : this(
name = key.name,
index = key.index,
key = key.key,
oldKey = key.oldKey,
boundNetKeyIndex = key.boundNetKeyIndex,
boundNetworkKey = key.boundNetworkKey,
boundNetKeyIndex = key.boundNetworkKey.index,
boundNetworkKeyName = key.boundNetworkKey.name,
isInUse = key.isInUse
)

Expand All @@ -55,7 +57,6 @@ data class ApplicationKeyData(
if (!oldKey.contentEquals(other.oldKey)) return false
} else if (other.oldKey != null) return false
if (boundNetKeyIndex != other.boundNetKeyIndex) return false
if (boundNetworkKey != other.boundNetworkKey) return false
if (isInUse != other.isInUse) return false

return true
Expand All @@ -67,7 +68,6 @@ data class ApplicationKeyData(
result = 31 * result + key.contentHashCode()
result = 31 * result + (oldKey?.contentHashCode() ?: 0)
result = 31 * result + boundNetKeyIndex.hashCode()
result = 31 * result + (boundNetworkKey?.hashCode() ?: 0)
result = 31 * result + isInUse.hashCode()
return result
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package no.nordicsemi.android.nrfmesh.core.data.models

import no.nordicsemi.android.nrfmesh.core.common.KeyIdGenerator
import kotlin.time.Instant
import no.nordicsemi.kotlin.mesh.core.model.KeyIndex
import no.nordicsemi.kotlin.mesh.core.model.KeyRefreshPhase
Expand Down Expand Up @@ -56,7 +57,8 @@ data class NetworkKeyData internal constructor(
val oldNetworkId: ByteArray?,
val timestamp: Instant,
val isPrimary: Boolean,
val isInUse: Boolean
val isInUse: Boolean,
val id: Long = KeyIdGenerator.nextId(),
) {
/**
* Convenience constructor for creating a new network key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ data class NodeData internal constructor(
excluded = node.excluded,
heartbeatPublication = node.heartbeatPublication,
heartbeatSubscription = node.heartbeatSubscription,
primaryElementData = node.primaryElement?.let { ElementData(it) },
primaryElementData = ElementData(node.primaryElement),
elementsCount = node.elementsCount,
addresses = node.addresses,
unicastRange = node.unicastRange,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package no.nordicsemi.android.nrfmesh.core.data.models

import no.nordicsemi.android.nrfmesh.core.common.KeyIdGenerator
import no.nordicsemi.kotlin.mesh.core.model.GroupRange
import no.nordicsemi.kotlin.mesh.core.model.Provisioner
import no.nordicsemi.kotlin.mesh.core.model.SceneRange
Expand All @@ -10,6 +11,18 @@ import kotlin.uuid.Uuid

/**
* ProvisionerData is a data class that represents a Provisioner in the Mesh network.
*
* @param name Name of the provisioner.
* @param uuid UUID of the provisioner.
* @param address Unicast address of the provisioner.
* @param ttl Default TTL value for the provisioner.
* @param deviceKey Device key of the provisioner in hexadecimal string format.
* @param unicastRanges List of unicast address ranges allocated to the provisioner.
* @param groupRanges List of group address ranges allocated to the provisioner.
* @param sceneRanges List of scene ranges allocated to the provisioner.
* @param hasConfigurationCapabilities Indicates if the provisioner has configuration capabilities.
* @param id A unique identifier for the ProvisionerData instance.
*
*/
@OptIn(ExperimentalUuidApi::class)
data class ProvisionerData(
Expand All @@ -21,7 +34,8 @@ data class ProvisionerData(
val unicastRanges: List<UnicastRange> = emptyList(),
val groupRanges: List<GroupRange> = emptyList(),
val sceneRanges: List<SceneRange> = emptyList(),
val hasConfigurationCapabilities: Boolean = false
val hasConfigurationCapabilities: Boolean = false,
val id: Long = KeyIdGenerator.nextId()
) {
@OptIn(ExperimentalStdlibApi::class)
constructor(provisioner: Provisioner) : this(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package no.nordicsemi.android.nrfmesh.core.data.models

import no.nordicsemi.android.nrfmesh.core.common.KeyIdGenerator
import no.nordicsemi.kotlin.mesh.core.model.Scene
import no.nordicsemi.kotlin.mesh.core.model.UnicastAddress

Expand All @@ -14,12 +15,14 @@ typealias SceneNumber = UShort
* @property number Scene number.
* @property addresses Addresses containing the scene.
* @property isInUse Defines whether the scene is in use by a node.
* @property id Unique ID for the scene data.
*/
data class SceneData(
val name: String,
val number: SceneNumber,
val addresses: List<UnicastAddress>,
val isInUse: Boolean
val isInUse: Boolean,
val id: Long = KeyIdGenerator.nextId(),
) {
constructor(scene: Scene) : this(
name = scene.name,
Expand Down
2 changes: 1 addition & 1 deletion core/ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ dependencies {
androidTestImplementation(libs.androidx.test.rules)

implementation("androidx.compose.material3:material3:1.4.0")
implementation("androidx.compose.material3:material3-adaptive-navigation-suite-android:1.4.0")
implementation("androidx.compose.material3:material3-adaptive-navigation-suite:1.4.0")
implementation("androidx.compose.material3.adaptive:adaptive:1.2.0")
implementation("androidx.compose.material3.adaptive:adaptive-layout-android:1.2.0")
implementation("androidx.compose.material3.adaptive:adaptive-navigation-android:1.2.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ private fun NonClickableElevatedCardItem(
},
title = title,
subtitle = subtitle,
subtitleMaxLines = subtitleMaxLines,
subtitleMaxLines = subtitleMaxLines,
trailingComposable = titleAction
)
if (supportingText != null)
Expand Down Expand Up @@ -177,7 +177,7 @@ private fun ClickableElevatedCardItem(
},
title = title,
subtitle = subtitle,
subtitleMaxLines = subtitleMaxLines,
subtitleMaxLines = subtitleMaxLines,
trailingComposable = titleAction
)
if (supportingText != null)
Expand Down Expand Up @@ -306,7 +306,8 @@ fun ElevatedCardItemTextField(
content = {
Icon(
imageVector = Icons.Outlined.DeleteSweep,
contentDescription = null
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
}
)
Expand All @@ -333,7 +334,7 @@ fun ElevatedCardItemTextField(
Icon(
imageVector = Icons.Outlined.Close,
contentDescription = null,
tint = LocalContentColor.current.copy(alpha = 0.6f)
tint = MaterialTheme.colorScheme.primary
)
}
)
Expand All @@ -353,7 +354,7 @@ fun ElevatedCardItemTextField(
Icon(
imageVector = Icons.Outlined.Check,
contentDescription = null,
tint = LocalContentColor.current.copy(alpha = 0.6f)
tint = MaterialTheme.colorScheme.primary
)
}
)
Expand Down Expand Up @@ -440,7 +441,8 @@ fun ElevatedCardItemHexTextField(
content = {
Icon(
imageVector = Icons.Outlined.DeleteSweep,
contentDescription = null
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
}
)
Expand All @@ -467,7 +469,7 @@ fun ElevatedCardItemHexTextField(
Icon(
imageVector = Icons.Outlined.Close,
contentDescription = null,
tint = LocalContentColor.current.copy(alpha = 0.6f)
tint = MaterialTheme.colorScheme.primary
)
}
)
Expand All @@ -487,7 +489,7 @@ fun ElevatedCardItemHexTextField(
Icon(
imageVector = Icons.Outlined.Check,
contentDescription = null,
tint = LocalContentColor.current.copy(alpha = 0.6f)
tint = MaterialTheme.colorScheme.primary
)
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import androidx.compose.ui.unit.dp
fun MeshOutlinedButton(
modifier: Modifier = Modifier,
isOnClickActionInProgress: Boolean = false,
buttonIcon: ImageVector? = null,
buttonIcon: ImageVector,
buttonIconTint: Color? = null,
text: String,
textColor: Color = Color.Unspecified,
Expand All @@ -54,7 +54,7 @@ fun MeshOutlinedButton(
color = buttonIconTint ?: ProgressIndicatorDefaults.circularColor
)
} else {
buttonIcon?.let {
buttonIcon.let {
Icon(
imageVector = it,
contentDescription = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,15 @@ fun MeshOutlinedTextField(
enabled = enabled,
prefix = prefix,
value = value,
onValueChange = onValueChanged,
onValueChange = { value ->
regex?.let {
if(it.matches(value.text)) {
onValueChanged(value)
}
} ?: run {
onValueChanged(value)
}
},
label = label,
placeholder = placeholder,
trailingIcon = internalTrailingIcon,
Expand Down
Loading