Skip to content

Commit

Permalink
Add support for additional thing state like online and vendor (#260)
Browse files Browse the repository at this point in the history
  • Loading branch information
kimble authored Feb 14, 2024
1 parent 7fdd3ec commit c7f630f
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 8 deletions.
40 changes: 40 additions & 0 deletions adapter-protobuf-java/src/main/proto/adapter.proto
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ message TextContent {
// locked, unlocked, open, close, offline, online etc. Implementing this can
// help administrators of Oslonøkkelen to configure alerts when things go
// offline, remain open too long etc.
//
// Not all devices will support reporting all this information. Just add those
// your device supports. Example: Don't send "online = false" if your device
// does not support online/offline reporting.
message ThingState {

// ISO-8601
Expand All @@ -330,6 +334,15 @@ message ThingState {
// be communicated to Oslonøkkelen
DebugLog debug_log = 7;

// Information about the device like vendor and model.
DeviceInfo device_type = 8;

// Is the device online right now? When was the last time it was seen?
Online online = 9;

// Rough indicator of battery health
BatteryStatus battery_status = 10;

}

reserved 4;
Expand Down Expand Up @@ -364,6 +377,33 @@ message ThingState {

}

// All fields are optional, but make sure you include at least
// one of the fields. If your device does not support either of these
// fields you should omit the DeviceInfo from your manifest.
message DeviceInfo {
string vendor = 1;
string model = 2;
string firmware_version = 3;
}

enum BatteryStatus {

// The battery should have been replaced already
EMPTY = 0;

// No need to change the battery
GOOD = 1;

// Battery should be replaced as soon as possible
POOR = 2;
}

message Online {
bool is_online = 1;

// ISO-8601
string last_seen = 2;
}

// Used to communicate a few lines of technical logs to Oslonøkkelen.
message DebugLog {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import com.github.oslokommune.oslonokkelen.adapter.error.ErrorCodeDescription
import com.github.oslokommune.oslonokkelen.adapter.error.ErrorCodes
import com.github.oslokommune.oslonokkelen.adapter.manifest.ManifestSnapshot
import com.github.oslokommune.oslonokkelen.adapter.proto.Adapter
import com.github.oslokommune.oslonokkelen.adapter.proto.Adapter.ThingState.BatteryStatus.EMPTY
import com.github.oslokommune.oslonokkelen.adapter.proto.Adapter.ThingState.BatteryStatus.GOOD
import com.github.oslokommune.oslonokkelen.adapter.proto.Adapter.ThingState.BatteryStatus.POOR
import com.github.oslokommune.oslonokkelen.adapter.proto.Adapter.ThingState.BatteryStatus.UNRECOGNIZED
import com.github.oslokommune.oslonokkelen.adapter.thing.ThingDescription
import com.github.oslokommune.oslonokkelen.adapter.thing.ThingId
import com.github.oslokommune.oslonokkelen.adapter.thing.ThingState
Expand All @@ -30,7 +34,7 @@ object ProtobufParser {
private val log: Logger = LoggerFactory.getLogger(ProtobufParser::class.java)


fun parseActionRequestFromClaims(verifiedClaims: JWTClaimsSet) : Adapter.ActionRequest {
fun parseActionRequestFromClaims(verifiedClaims: JWTClaimsSet): Adapter.ActionRequest {
val requestClaim = verifiedClaims.getJSONObjectClaim("request")
val requestBuilder = Adapter.ActionRequest.newBuilder()
.setRequestId(requireString(requestClaim, "requestId"))
Expand All @@ -46,11 +50,14 @@ object ProtobufParser {
val value = attachment.values.firstOrNull() as Map<*, *>

Adapter.Attachment.newBuilder()
.setNorwegianFodselsnummer(Adapter.Attachment.NorwegianFodselsnummer.newBuilder()
.setNumber(requireString(value, "number"))
.build())
.setNorwegianFodselsnummer(
Adapter.Attachment.NorwegianFodselsnummer.newBuilder()
.setNumber(requireString(value, "number"))
.build()
)
.build()
}

else -> {
null
}
Expand Down Expand Up @@ -82,7 +89,7 @@ object ProtobufParser {
return value ?: throw missingKey(key, requestClaim)
}

private fun missingKey(key: String,requestClaim: Map<*, *>): IllegalStateException {
private fun missingKey(key: String, requestClaim: Map<*, *>): IllegalStateException {
return IllegalStateException("Missing key $key (found: ${requestClaim.keys.joinToString(", ")})")
}

Expand Down Expand Up @@ -240,6 +247,41 @@ object ProtobufParser {
)
}

Adapter.ThingState.ValueCase.DEVICE_TYPE -> {
ThingState.DeviceType(
thingId = thing.id,
timestamp = lastUpdate,
vendor = serializedState.deviceType.vendor.ifBlank { null },
model = serializedState.deviceType.model.ifBlank { null },
firmwareVersion = serializedState.deviceType.firmwareVersion.ifBlank { null }
)
}

Adapter.ThingState.ValueCase.ONLINE -> {
ThingState.Online(
thingId = thing.id,
timestamp = lastUpdate,
online = serializedState.online.isOnline,
lastSeen = if (serializedState.online.lastSeen.isNotBlank()) {
Instant.parse(serializedState.online.lastSeen)
} else {
null
}
)
}

Adapter.ThingState.ValueCase.BATTERY_STATUS -> {
ThingState.BatteryStatus(
thingId = thing.id,
timestamp = lastUpdate,
state = when (serializedState.batteryStatus) {
GOOD -> ThingState.BatteryStatus.State.GOOD
POOR -> ThingState.BatteryStatus.State.POOR
EMPTY, UNRECOGNIZED, null -> ThingState.BatteryStatus.State.EMPTY
}
)
}

Adapter.ThingState.ValueCase.VALUE_NOT_SET, null -> {
log.warn("Unsupported thing state detected: {}", serializedState.valueCase)
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,48 @@ object ProtobufSerializer {
)
.build()
}

is ThingState.BatteryStatus -> {
Adapter.ThingState.newBuilder()
.setLastUpdate(state.timestamp.toString())
.setBatteryStatus(when (state.state) {
ThingState.BatteryStatus.State.EMPTY -> Adapter.ThingState.BatteryStatus.EMPTY
ThingState.BatteryStatus.State.GOOD -> Adapter.ThingState.BatteryStatus.GOOD
ThingState.BatteryStatus.State.POOR -> Adapter.ThingState.BatteryStatus.POOR
})
.build()
}
is ThingState.DeviceType -> {
val deviceInfoBuilder = Adapter.ThingState.DeviceInfo.newBuilder()

if (state.vendor != null) {
deviceInfoBuilder.setVendor(state.vendor)
}
if (state.model != null) {
deviceInfoBuilder.setModel(state.model)
}
if (state.firmwareVersion != null) {
deviceInfoBuilder.setFirmwareVersion(state.firmwareVersion)
}

Adapter.ThingState.newBuilder()
.setLastUpdate(state.timestamp.toString())
.setDeviceType(deviceInfoBuilder.build())
.build()
}
is ThingState.Online -> {
val onlineBuilder = Adapter.ThingState.Online.newBuilder()
onlineBuilder.setIsOnline(state.online)

if (state.lastSeen != null) {
onlineBuilder.setLastSeen(state.lastSeen.toString())
}

Adapter.ThingState.newBuilder()
.setLastUpdate(state.timestamp.toString())
.setOnline(onlineBuilder.build())
.build()
}
}
} ?: emptyList()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,44 @@ sealed class ThingState {

}

data class BatteryStatus(
override val timestamp: Instant,
override val thingId: ThingId,
val state: State
) : ThingState() {

override val key = Key(thingId, "thing.${thingId.value}.battery")

enum class State {
EMPTY, GOOD, POOR
}

}

data class Online(
override val timestamp: Instant,
override val thingId: ThingId,
val lastSeen: Instant?,
val online: Boolean
) : ThingState() {

override val key = Key(thingId, "thing.${thingId.value}.online")

}

data class DeviceType(
override val timestamp: Instant,
override val thingId: ThingId,
val vendor: String?,
val model: String?,
val firmwareVersion: String?
) : ThingState() {

override val key = Key(thingId, "thing.${thingId.value}.online")

}


data class Key(
val thingId: ThingId,
val value: String
Expand Down
6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ allprojects {

pluginManager.withPlugin("kotlin") {
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = JavaVersion.VERSION_18.toString()
kotlinOptions.jvmTarget = JavaVersion.VERSION_21.toString()
}
}
pluginManager.withPlugin("java") {
tasks.withType<JavaCompile> {
targetCompatibility = JavaVersion.VERSION_18.toString()
sourceCompatibility = JavaVersion.VERSION_18.toString()
targetCompatibility = JavaVersion.VERSION_21.toString()
sourceCompatibility = JavaVersion.VERSION_21.toString()
}
}
}
Expand Down

0 comments on commit c7f630f

Please sign in to comment.