Skip to content

Commit

Permalink
Add DeviceRegistration.additionalSpecifications
Browse files Browse the repository at this point in the history
  • Loading branch information
yuanchen233 authored and Whathecode committed Oct 6, 2024
1 parent 94664ce commit 3fdd269
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package dk.cachet.carp.common.application.devices

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.application.Trilean
import dk.cachet.carp.common.application.UUID
import dk.cachet.carp.common.application.data.CarpDataTypes
Expand Down Expand Up @@ -78,7 +79,8 @@ data class AltBeaconDeviceRegistration(
*/
val referenceRssi: Short,
@Required
override val deviceDisplayName: String? = null // TODO: We could map known manufacturerId's to display names.
override val deviceDisplayName: String? = null, // TODO: We could map known manufacturerId's to display names.
override val additionalSpecifications: ApplicationData? = null
) : DeviceRegistration()
{
companion object
Expand Down Expand Up @@ -134,6 +136,7 @@ class AltBeaconDeviceRegistrationBuilder : DeviceRegistrationBuilder<AltBeaconDe
majorId,
minorId,
referenceRssi,
deviceDisplayName
deviceDisplayName,
additionalSpecifications
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dk.cachet.carp.common.application.devices

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.infrastructure.serialization.NotSerializable
import kotlinx.serialization.*
import kotlin.js.JsExport
Expand All @@ -15,7 +16,8 @@ import kotlin.js.JsExport
data class BLESerialNumberDeviceRegistration(
val serialNumber: String,
@Required
override val deviceDisplayName: String? = null
override val deviceDisplayName: String? = null,
override val additionalSpecifications: ApplicationData? = null
) : DeviceRegistration()
{
init
Expand All @@ -41,5 +43,5 @@ class BLESerialNumberDeviceRegistrationBuilder : DeviceRegistrationBuilder<BLESe
var serialNumber: String = ""

override fun build(): BLESerialNumberDeviceRegistration =
BLESerialNumberDeviceRegistration( serialNumber, deviceDisplayName )
BLESerialNumberDeviceRegistration( serialNumber, deviceDisplayName, additionalSpecifications )
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dk.cachet.carp.common.application.devices

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.application.UUID
import dk.cachet.carp.common.infrastructure.serialization.NotSerializable
import kotlinx.serialization.*
Expand All @@ -16,6 +17,7 @@ import kotlin.js.JsExport
data class DefaultDeviceRegistration(
@Required
override val deviceDisplayName: String? = null,
override val additionalSpecifications: ApplicationData? = null,
@Required
override val deviceId: String = UUID.randomUUID().toString()
) : DeviceRegistration()
Expand All @@ -36,5 +38,6 @@ class DefaultDeviceRegistrationBuilder : DeviceRegistrationBuilder<DefaultDevice
*/
var deviceId: String = UUID.randomUUID().toString()

override fun build(): DefaultDeviceRegistration = DefaultDeviceRegistration( deviceDisplayName, deviceId )
override fun build(): DefaultDeviceRegistration =
DefaultDeviceRegistration( deviceDisplayName, additionalSpecifications, deviceId )
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package dk.cachet.carp.common.application.devices

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.application.Immutable
import dk.cachet.carp.common.application.ImplementAsDataClass
import dk.cachet.carp.common.infrastructure.serialization.NotSerializable
Expand Down Expand Up @@ -42,6 +43,12 @@ abstract class DeviceRegistration

@Required
val registrationCreatedOn: Instant = Clock.System.now()

/**
* Additional device specifications which may be relevant to the researcher when interpreting collected data.
* E.g., brand/model name, operating system version, or any other relevant information.
*/
abstract val additionalSpecifications: ApplicationData?
}


Expand All @@ -65,6 +72,12 @@ abstract class DeviceRegistrationBuilder<T : DeviceRegistration>
*/
var deviceDisplayName: String? = null

/**
* Additional device specifications which may be relevant to the researcher when interpreting collected data.
* E.g., brand/model name, operating system version, or any other relevant information.
*/
var additionalSpecifications: ApplicationData? = null

/**
* Build the immutable [DeviceRegistration] using the current configuration of this [DeviceRegistrationBuilder].
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dk.cachet.carp.common.application.devices

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.application.MACAddress
import dk.cachet.carp.common.infrastructure.serialization.NotSerializable
import kotlinx.serialization.*
Expand All @@ -14,7 +15,8 @@ import kotlin.js.JsExport
data class MACAddressDeviceRegistration(
val macAddress: MACAddress,
@Required
override val deviceDisplayName: String? = null
override val deviceDisplayName: String? = null,
override val additionalSpecifications: ApplicationData? = null
) : DeviceRegistration()
{
@Required
Expand All @@ -30,5 +32,5 @@ class MACAddressDeviceRegistrationBuilder : DeviceRegistrationBuilder<MACAddress
var macAddress: String = ""

override fun build(): MACAddressDeviceRegistration =
MACAddressDeviceRegistration( MACAddress.parse( macAddress ), deviceDisplayName )
MACAddressDeviceRegistration( MACAddress.parse( macAddress ), deviceDisplayName, additionalSpecifications )
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package dk.cachet.carp.common.application.devices

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.application.Trilean
import dk.cachet.carp.common.application.data.DataType
import dk.cachet.carp.common.application.sampling.DataTypeSamplingSchemeMap
Expand Down Expand Up @@ -51,7 +52,8 @@ data class WebsiteDeviceRegistration(
*/
val userAgent: String,
@Required
override val deviceDisplayName: String? = userAgent
override val deviceDisplayName: String? = userAgent,
override val additionalSpecifications: ApplicationData? = null
) : DeviceRegistration()
{
@Required
Expand All @@ -74,5 +76,6 @@ class WebsiteDeviceRegistrationBuilder : DeviceRegistrationBuilder<WebsiteDevice
*/
var userAgent: String = ""

override fun build(): WebsiteDeviceRegistration = WebsiteDeviceRegistration( url, userAgent, deviceDisplayName )
override fun build(): WebsiteDeviceRegistration =
WebsiteDeviceRegistration( url, userAgent, deviceDisplayName, additionalSpecifications )
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dk.cachet.carp.common.infrastructure.serialization

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.application.Trilean
import dk.cachet.carp.common.application.data.DataType
import dk.cachet.carp.common.application.devices.AnyDeviceConfiguration
Expand Down Expand Up @@ -178,18 +179,21 @@ data class CustomDeviceRegistration internal constructor(
@Serializable
private data class BaseMembers(
override val deviceId: String,
override val deviceDisplayName: String?
override val deviceDisplayName: String?,
override val additionalSpecifications: ApplicationData? = null
) : DeviceRegistration()

override val deviceId: String
override val deviceDisplayName: String?
override val additionalSpecifications: ApplicationData?

init
{
val json = Json( serializer ) { ignoreUnknownKeys = true }
val baseMembers = json.decodeFromString( BaseMembers.serializer(), jsonSource )
deviceId = baseMembers.deviceId
deviceDisplayName = baseMembers.deviceDisplayName
additionalSpecifications = baseMembers.additionalSpecifications
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package dk.cachet.carp.common.infrastructure.serialization

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.application.devices.DefaultDeviceRegistration
import dk.cachet.carp.common.application.devices.DeviceRegistration
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import dk.cachet.carp.common.infrastructure.test.makeUnknown
import kotlinx.serialization.*
import kotlin.test.*


Expand All @@ -15,12 +16,12 @@ class DeviceRegistrationTest
@Test
fun can_serialize_and_deserialize_device_registration_using_JSON()
{
val default: DeviceRegistration = DefaultDeviceRegistration()

val serialized = testJson.encodeToString( DeviceRegistration.serializer(), default )
val parsed: DeviceRegistration = testJson.decodeFromString( serialized )

assertEquals( default, parsed )
val toSerialize = getTestCases()
toSerialize.forEach {
val serialized = testJson.encodeToString( DeviceRegistration.serializer(), it )
val parsed: DeviceRegistration = testJson.decodeFromString( serialized )
assertEquals( it, parsed )
}
}

/**
Expand All @@ -29,10 +30,12 @@ class DeviceRegistrationTest
@Test
fun unknown_types_are_wrapped_when_deserializing()
{
val unknownRegistration = serializeUnknownDeviceRegistration()
val parsed: DeviceRegistration = testJson.decodeFromString( unknownRegistration )

assertTrue( parsed is CustomDeviceRegistration )
val toSerialize = getTestCases()
toSerialize.forEach {
val unknownRegistration = serializeUnknownDeviceRegistration( it )
val parsed: DeviceRegistration = testJson.decodeFromString( unknownRegistration )
assertTrue( parsed is CustomDeviceRegistration )
}
}

/**
Expand All @@ -41,18 +44,33 @@ class DeviceRegistrationTest
@Test
fun serializing_unknown_types_removes_the_wrapper()
{
val unknownRegistration = serializeUnknownDeviceRegistration()
val parsed: DeviceRegistration = testJson.decodeFromString( unknownRegistration )

val serialized = testJson.encodeToString( parsed )
assertEquals( unknownRegistration, serialized )
val toSerialize = getTestCases()
toSerialize.forEach {
val unknownRegistration = serializeUnknownDeviceRegistration( it )
val parsed: DeviceRegistration = testJson.decodeFromString( unknownRegistration )
val serialized = testJson.encodeToString( parsed )
assertEquals( unknownRegistration, serialized )
}
}

private fun serializeUnknownDeviceRegistration(): String
private fun getTestCases() = listOf(
// With null values.
DefaultDeviceRegistration(),

// With all nullable fields set.
DefaultDeviceRegistration(
deviceDisplayName = "Device name",
additionalSpecifications = ApplicationData( """{"OS":"Android 42"}""" )
)
)

/**
* Serialize [registration] as an unknown type using JSON.
*/
private fun serializeUnknownDeviceRegistration( registration: DeviceRegistration ): String
{
val registration = DefaultDeviceRegistration()
var serialized = testJson.encodeToString( DeviceRegistration.serializer(), registration )
serialized = serialized.replace( "dk.cachet.carp.common.application.devices.DefaultDeviceRegistration", "com.unknown.CustomRegistration" )
serialized = serialized.makeUnknown( registration )

return serialized
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dk.cachet.carp.deployments.application

import dk.cachet.carp.common.application.ApplicationData
import dk.cachet.carp.common.application.UUID
import dk.cachet.carp.common.application.devices.DefaultDeviceRegistration
import dk.cachet.carp.common.application.devices.DeviceRegistration
Expand Down Expand Up @@ -158,6 +159,7 @@ class ValidationTest
{
override val deviceId: String = "Invalid"
override val deviceDisplayName: String? = null
override val additionalSpecifications: ApplicationData? = null
}
val preregistrations = mapOf( connectedRoleName to invalidRegistration )

Expand Down
3 changes: 2 additions & 1 deletion rpc/schemas/common/devices/DeviceRegistration.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"__type": true,
"deviceId": { "type": "string" },
"deviceDisplayName": { "type": [ "string", "null" ] },
"registrationCreatedOn": { "type": "string", "format": "date-time" }
"registrationCreatedOn": { "type": "string", "format": "date-time" },
"additionalSpecifications": { "$ref": "../../common/ApplicationData.json" }
},
"required": [ "__type", "deviceId", "deviceDisplayName", "registrationCreatedOn" ]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ private val bikeBeaconPreregistration = bikeBeacon.createRegistration {
organizationId = UUID( "4e990957-0838-414c-bf25-2d391e2990b5" )
majorId = 42
minorId = 42
additionalSpecifications = ApplicationData( """{"Model": "AnyBeacon B42"}""" )
}.setRegistrationCreatedOn( deploymentCreatedOn )
private val phoneRegistration = phone.createRegistration {
deviceId = UUID( "fc7b41b0-e9e2-4b5d-8c3d-5119b556a3f0" ).toString()
Expand Down

0 comments on commit 3fdd269

Please sign in to comment.