Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,9 @@ class Topics(vararg val topics: String) {
/** MQTT topic string for the "ChangePersonMetadataValueMapi" command. */
val CHANGE_PERSON_METADATA_VALUE = "xs3/1/cmd/ChangePersonMetadataValueMapi"

/** MQTT topic string for the "ChangeInstallationPointMetadataValueMapi" command. */
val CHANGE_INSTALLATION_POINT_METADATA_VALUE =
"xs3/1/cmd/ChangeInstallationPointMetadataValueMapi"
/** MQTT topic string for the "ChangeAuthorizationProfileMetadataValueMapi" command. */
val CHANGE_AUTHORIZATION_PROFILE_METADATA_VALUE =
"xs3/1/cmd/ChangeAuthorizationProfileMetadataValueMapi"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,3 +486,32 @@ suspend fun XesarConnect.configureBluetoothStateAsync(
requestConfig,
)
}

/**
* Changes the value of custom data field of an installation point.
*
* @param id The ID of the installation point.
* @param metadataId The metadataID of the data field.
* @param value The new value of the field.
* @param requestConfig The request configuration (optional).
*/
suspend fun XesarConnect.changeInstallationPointMetadataValueAsync(
id: UUID,
metadataId: UUID,
value: String,
requestConfig: XesarConnect.RequestConfig = buildRequestConfig(),
): SingleEventResult<InstallationPointChanged> {
return sendCommandAsync<ChangeInstallationPointMetadataValueMapi, InstallationPointChanged>(
Topics.Command.CHANGE_INSTALLATION_POINT_METADATA_VALUE,
Topics.Event.INSTALLATION_POINT_CHANGED,
true,
ChangeInstallationPointMetadataValueMapi(
config.uuidGenerator.generateId(),
id,
metadataId,
value,
token,
),
requestConfig,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.open200.xesar.connect.messages.command

import com.open200.xesar.connect.utils.UUIDSerializer
import java.util.*
import kotlinx.serialization.Serializable

/**
* Represents a command POJO to change a custom data field value for an installation point.
*
* @param commandId The id of the command.
* @param id The id of the installation point.
* @param metadataId The id of the custom data field.
* @param value The new value of the custom data field.
* @param token The token of the command.
*/
@Serializable
data class ChangeInstallationPointMetadataValueMapi(
override val commandId: @Serializable(with = UUIDSerializer::class) UUID,
val id: @Serializable(with = UUIDSerializer::class) UUID,
val metadataId: @Serializable(with = UUIDSerializer::class) UUID,
val value: String,
val token: String,
) : Command
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.open200.xesar.connect.messages.event

import com.open200.xesar.connect.messages.BluetoothState
import com.open200.xesar.connect.messages.EntityMetadata
import com.open200.xesar.connect.messages.PersonalLog
import com.open200.xesar.connect.messages.query.TimeProfile
import com.open200.xesar.connect.utils.UUIDSerializer
Expand Down Expand Up @@ -28,6 +29,8 @@ import kotlinx.serialization.Serializable
* @param timeProfileData The time profile data.
* @param openDoor Whether the door is open.
* @param bluetoothState The Bluetooth state of the installation point (optional).
* @param entityMetadata Contains the information for all defined custom data fields for the
* installation point.
*/
@Serializable
data class InstallationPointChanged(
Expand All @@ -50,4 +53,5 @@ data class InstallationPointChanged(
val timeProfileData: TimeProfile? = null,
val openDoor: Boolean? = null,
val bluetoothState: BluetoothState? = null,
val entityMetadata: List<EntityMetadata>? = null,
) : Event
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.open200.xesar.connect.messages.query

import com.open200.xesar.connect.messages.BluetoothState
import com.open200.xesar.connect.messages.ComponentType
import com.open200.xesar.connect.messages.EntityMetadata
import com.open200.xesar.connect.utils.UUIDSerializer
import java.util.*
import kotlinx.serialization.Serializable
Expand Down Expand Up @@ -34,6 +35,8 @@ import kotlinx.serialization.Serializable
* @param accessId The access ID of the installation point (optional).
* @param secure Indicates if the installation point is secure (optional).
* @param bluetoothState The Bluetooth state of the installation point (optional).
* @param entityMetadata Contains the information for all defined custom data fields for the
* installation point.
*/
@Serializable
data class InstallationPoint(
Expand All @@ -60,6 +63,7 @@ data class InstallationPoint(
val accessId: Long? = null,
val secure: Boolean? = null,
val bluetoothState: BluetoothState? = null,
val entityMetadata: List<EntityMetadata>? = null,
) : QueryListResource, QueryElementResource {
companion object {
const val QUERY_RESOURCE = "installation-points"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class InstallationPointElementTest :
)

val installationPointString =
"{\"requestId\":\"00000000-1281-42c0-9a15-c5844850c748\",\"response\":{\"id\":\"7ca59670-bd30-4ea9-9bd1-2103a9bd2f2a\",\"name\":\"door 1 entry point\",\"description\":\"door 1\",\"installationId\":\"1a61d397-0afc-436a-8b75-521577d2aa02\",\"installationType\":\"door 1\",\"linkedInstallationPoints\":[\"ed6236d0-a47c-46be-8495-d4755c38f103\",\"7cbcddaa-50c3-48fb-8e5a-56bab47d8f81\"],\"onlineStatus\":\"connected\",\"componentType\":\"Cylinder\",\"releaseDurationShort\":5,\"releaseDurationLong\":20,\"logMode\":\"dontSave\",\"days\":30,\"manualOfficeMode\":false,\"shopMode\":false,\"openDoor\":true,\"bleStatus\":\"NO_BLE\",\"timeProfileName\":null,\"batteryCondition\":null,\"timeProfileId\":null,\"accessId\":null,\"secure\":null,\"bluetoothState\":null}}"
"{\"requestId\":\"00000000-1281-42c0-9a15-c5844850c748\",\"response\":{\"id\":\"7ca59670-bd30-4ea9-9bd1-2103a9bd2f2a\",\"name\":\"door 1 entry point\",\"description\":\"door 1\",\"installationId\":\"1a61d397-0afc-436a-8b75-521577d2aa02\",\"installationType\":\"door 1\",\"linkedInstallationPoints\":[\"ed6236d0-a47c-46be-8495-d4755c38f103\",\"7cbcddaa-50c3-48fb-8e5a-56bab47d8f81\"],\"onlineStatus\":\"connected\",\"componentType\":\"Cylinder\",\"releaseDurationShort\":5,\"releaseDurationLong\":20,\"logMode\":\"dontSave\",\"days\":30,\"manualOfficeMode\":false,\"shopMode\":false,\"openDoor\":true,\"bleStatus\":\"NO_BLE\",\"timeProfileName\":null,\"batteryCondition\":null,\"timeProfileId\":null,\"accessId\":null,\"secure\":null,\"bluetoothState\":null,\"entityMetadata\":[{\"id\":\"123e4567-e89b-12d3-a456-426614174000\",\"name\":\"type\",\"value\":\"double door\"},{\"id\":\"0f8fad5b-d9cb-469f-a165-70867728950e\",\"name\":\"color\",\"value\":null}]}}"

Comment thread
PaulWinter91 marked this conversation as resolved.
test("encoding QueryResponseElement for an installation Point") {
val installationPointEncoded = encodeQueryElement(installationPoint)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class InstallationPointListTest :
)

val installationPointString =
"{\"requestId\":\"00000000-1281-40ae-89d7-5c541d77a757\",\"response\":{\"data\":[{\"id\":\"7ca59670-bd30-4ea9-9bd1-2103a9bd2f2a\",\"name\":\"door 1 entry point\",\"description\":\"door 1\",\"installationId\":\"1a61d397-0afc-436a-8b75-521577d2aa02\",\"installationType\":\"door 1\",\"linkedInstallationPoints\":[\"ed6236d0-a47c-46be-8495-d4755c38f103\",\"7cbcddaa-50c3-48fb-8e5a-56bab47d8f81\"],\"onlineStatus\":\"connected\",\"componentType\":\"Cylinder\",\"releaseDurationShort\":5,\"releaseDurationLong\":20,\"logMode\":\"dontSave\",\"days\":30,\"manualOfficeMode\":false,\"shopMode\":false,\"openDoor\":true,\"bleStatus\":\"NO_BLE\",\"timeProfileName\":null,\"batteryCondition\":null,\"timeProfileId\":null,\"accessId\":null,\"secure\":null,\"bluetoothState\":null},{\"id\":\"a4c838a8-f6be-49e0-abee-c1d3b2897279\",\"name\":\"door 2 entry point\",\"description\":\"door 2\",\"installationId\":\"0cefd48b-969e-43eb-aad6-98553288eb4d\",\"installationType\":\"door 2\",\"linkedInstallationPoints\":[\"ed6236d0-a47c-46be-8495-d4755c38f103\",\"7cbcddaa-50c3-48fb-8e5a-56bab47d8f81\"],\"onlineStatus\":\"connected\",\"componentType\":\"Cylinder\",\"releaseDurationShort\":5,\"releaseDurationLong\":20,\"logMode\":\"dontSave\",\"days\":30,\"manualOfficeMode\":false,\"shopMode\":false,\"openDoor\":true,\"bleStatus\":\"NO_BLE\",\"timeProfileName\":null,\"batteryCondition\":null,\"timeProfileId\":null,\"accessId\":null,\"secure\":null,\"bluetoothState\":null}],\"totalCount\":2,\"filterCount\":2}}"
"{\"requestId\":\"00000000-1281-40ae-89d7-5c541d77a757\",\"response\":{\"data\":[{\"id\":\"7ca59670-bd30-4ea9-9bd1-2103a9bd2f2a\",\"name\":\"door 1 entry point\",\"description\":\"door 1\",\"installationId\":\"1a61d397-0afc-436a-8b75-521577d2aa02\",\"installationType\":\"door 1\",\"linkedInstallationPoints\":[\"ed6236d0-a47c-46be-8495-d4755c38f103\",\"7cbcddaa-50c3-48fb-8e5a-56bab47d8f81\"],\"onlineStatus\":\"connected\",\"componentType\":\"Cylinder\",\"releaseDurationShort\":5,\"releaseDurationLong\":20,\"logMode\":\"dontSave\",\"days\":30,\"manualOfficeMode\":false,\"shopMode\":false,\"openDoor\":true,\"bleStatus\":\"NO_BLE\",\"timeProfileName\":null,\"batteryCondition\":null,\"timeProfileId\":null,\"accessId\":null,\"secure\":null,\"bluetoothState\":null,\"entityMetadata\":[{\"id\":\"123e4567-e89b-12d3-a456-426614174000\",\"name\":\"type\",\"value\":\"double door\"},{\"id\":\"0f8fad5b-d9cb-469f-a165-70867728950e\",\"name\":\"color\",\"value\":null}]},{\"id\":\"a4c838a8-f6be-49e0-abee-c1d3b2897279\",\"name\":\"door 2 entry point\",\"description\":\"door 2\",\"installationId\":\"0cefd48b-969e-43eb-aad6-98553288eb4d\",\"installationType\":\"door 2\",\"linkedInstallationPoints\":[\"ed6236d0-a47c-46be-8495-d4755c38f103\",\"7cbcddaa-50c3-48fb-8e5a-56bab47d8f81\"],\"onlineStatus\":\"connected\",\"componentType\":\"Cylinder\",\"releaseDurationShort\":5,\"releaseDurationLong\":20,\"logMode\":\"dontSave\",\"days\":30,\"manualOfficeMode\":false,\"shopMode\":false,\"openDoor\":true,\"bleStatus\":\"NO_BLE\",\"timeProfileName\":null,\"batteryCondition\":null,\"timeProfileId\":null,\"accessId\":null,\"secure\":null,\"bluetoothState\":null,\"entityMetadata\":[{\"id\":\"123e4567-e89b-12d3-a456-426614174000\",\"name\":\"type\",\"value\":\"double door\"},{\"id\":\"0f8fad5b-d9cb-469f-a165-70867728950e\",\"name\":\"color\",\"value\":null}]}],\"totalCount\":2,\"filterCount\":2}}"

Comment thread
PaulWinter91 marked this conversation as resolved.
test("encoding installationPointList for a list of installation Points") {
val installationPointEncoded = encodeQueryList(installationPointList)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.open200.xesar.connect.it.command

import com.open200.xesar.connect.Topics
import com.open200.xesar.connect.XesarConnect
import com.open200.xesar.connect.XesarMqttClient
import com.open200.xesar.connect.extension.changeInstallationPointMetadataValueAsync
import com.open200.xesar.connect.it.MosquittoContainer
import com.open200.xesar.connect.messages.EntityMetadata
import com.open200.xesar.connect.messages.event.ApiEvent
import com.open200.xesar.connect.messages.event.InstallationPointChanged
import com.open200.xesar.connect.messages.event.encodeEvent
import io.kotest.common.runBlocking
import io.kotest.core.spec.style.FunSpec
import io.kotest.extensions.testcontainers.perProject
import io.kotest.matchers.equals.shouldBeEqual
import io.mockk.coEvery
import java.util.*
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.launch

class ChangeInstallationPointMetadataValueTest :
FunSpec({
val container = MosquittoContainer.container()
val config = MosquittoContainer.config(container)
listener(container.perProject())

test("change installation point metadata value") {
coEvery { config.uuidGenerator.generateId() }
.returns(UUID.fromString("00000000-1281-40ae-89d7-5c541d77a757"))

val installationPointId = UUID.fromString("11111111-2222-3333-4444-555555555555")
val metadataId = UUID.fromString("aaaaaaaa-0000-0000-0000-000000000001")

runBlocking {
val simulatedBackendReady = CompletableDeferred<Unit>()
val commandReceived = CompletableDeferred<String>()

launch {
XesarMqttClient.connectAsync(config).await().use { client ->
client.subscribeAsync(arrayOf(Topics.ALL_TOPICS)).await()

client.onMessage = { topic, payload ->
when (topic) {
Topics.Command.CHANGE_INSTALLATION_POINT_METADATA_VALUE -> {
commandReceived.complete(payload.decodeToString())
}
}
}

simulatedBackendReady.complete(Unit)

val commandContent = commandReceived.await()

commandContent.shouldBeEqual(
"{\"commandId\":\"00000000-1281-40ae-89d7-5c541d77a757\",\"id\":\"11111111-2222-3333-4444-555555555555\",\"metadataId\":\"aaaaaaaa-0000-0000-0000-000000000001\",\"value\":\"Test Value\",\"token\":\"JDJhJDEwJDFSNEljZ2FaRUNXUXBTQ25XN05KbE9qRzFHQ1VjMzkvWTBVcFpZb1M4Vmt0dnJYZ0tJVFBx\"}"
)

val apiEvent =
ApiEvent(
UUID.fromString("00000000-1281-40ae-89d7-5c541d77a757"),
InstallationPointChanged(
aggregateId = installationPointId,
entityMetadata =
listOf(
EntityMetadata(
id = metadataId,
name = "test",
value = "Test Value",
)
),
),
)

client
.publishAsync(
Topics.Event.INSTALLATION_POINT_CHANGED,
encodeEvent(apiEvent),
)
.await()
}
}

launch {
simulatedBackendReady.await()

val api = XesarConnect.connectAndLoginAsync(config).await()
api.subscribeAsync(Topics(Topics.Event.INSTALLATION_POINT_CHANGED)).await()

val result =
api.changeInstallationPointMetadataValueAsync(
id = installationPointId,
metadataId = metadataId,
value = "Test Value",
)
.await()

result.aggregateId.shouldBeEqual(installationPointId)
result.entityMetadata!!
.single { it.id == metadataId }
.value
?.shouldBeEqual("Test Value")
}
}
}
})
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.open200.xesar.connect.util.fixture

import com.open200.xesar.connect.messages.ComponentType
import com.open200.xesar.connect.messages.EntityMetadata
import com.open200.xesar.connect.messages.query.InstallationPoint
import com.open200.xesar.connect.messages.query.OnlineStatus
import java.util.*
Expand Down Expand Up @@ -28,5 +29,18 @@ object InstallationPointFixture {
shopMode = false,
openDoor = true,
bleStatus = "NO_BLE",
entityMetadata =
listOf(
EntityMetadata(
id = UUID.fromString("123e4567-e89b-12d3-a456-426614174000"),
name = "type",
value = "double door",
),
EntityMetadata(
id = UUID.fromString("0f8fad5b-d9cb-469f-a165-70867728950e"),
name = "color",
value = null,
),
),
)
}
Loading