forked from OSGP/sng-crest-device-service
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request OSGP#74 from OSGP/feature/FDP-2551-command-result-…
…hander-refactoring Feature/fdp 2551 command result handler refactoring
- Loading branch information
Showing
33 changed files
with
1,256 additions
and
426 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
...gxf/crestdeviceservice/command/exception/NoCommandResultHandlerForCommandTypeException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.exception | ||
|
||
class NoCommandResultHandlerForCommandTypeException(message: String) : Exception(message) |
73 changes: 73 additions & 0 deletions
73
.../src/main/kotlin/org/gxf/crestdeviceservice/command/resulthandler/CommandResultHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.resulthandler | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.gxf.crestdeviceservice.command.entity.Command | ||
import org.gxf.crestdeviceservice.command.entity.Command.CommandType | ||
import org.gxf.crestdeviceservice.command.service.CommandFeedbackService | ||
import org.gxf.crestdeviceservice.command.service.CommandService | ||
import org.gxf.crestdeviceservice.model.ErrorUrc.Companion.getMessageFromCode | ||
|
||
abstract class CommandResultHandler( | ||
private val commandService: CommandService, | ||
private val commandFeedbackService: CommandFeedbackService | ||
) { | ||
private val logger = KotlinLogging.logger {} | ||
|
||
abstract val supportedCommandType: CommandType | ||
|
||
abstract fun hasSucceeded(deviceId: String, body: JsonNode): Boolean | ||
|
||
abstract fun hasFailed(deviceId: String, body: JsonNode): Boolean | ||
|
||
fun handleSuccess(command: Command) { | ||
logger.info { "Command ${command.type} succeeded for device with id ${command.deviceId}." } | ||
|
||
handleCommandSpecificSuccess(command) | ||
|
||
logger.debug { "Saving command and sending feedback to Maki." } | ||
val successfulCommand = commandService.saveCommand(command.finish()) | ||
commandFeedbackService.sendSuccessFeedback(successfulCommand) | ||
} | ||
|
||
/** Override this method when custom success actions are needed. */ | ||
open fun handleCommandSpecificSuccess(command: Command) { | ||
logger.debug { | ||
"Command ${command.type} for device with id ${command.deviceId} does not require specific success handling." | ||
} | ||
} | ||
|
||
fun handleFailure(command: Command, body: JsonNode) { | ||
logger.info { "Command ${command.type} failed for device with id ${command.deviceId}." } | ||
|
||
handleCommandSpecificFailure(command, body) | ||
|
||
val failedCommand = commandService.saveCommand(command.fail()) | ||
val errorMessages = body.urcs().joinToString(". ") { urc -> getMessageFromCode(urc) } | ||
commandFeedbackService.sendErrorFeedback(failedCommand, "Command failed. Error(s): $errorMessages.") | ||
} | ||
|
||
/** Override this method when command specific failure actions are needed */ | ||
open fun handleCommandSpecificFailure(command: Command, body: JsonNode) { | ||
logger.debug { | ||
"Command ${command.type} for device with id ${command.deviceId} does not require specific failure handling." | ||
} | ||
} | ||
|
||
fun handleStillInProgress(command: Command) { | ||
logger.info { "Command ${command.type} still in progress for device with id ${command.deviceId}." } | ||
} | ||
|
||
companion object { | ||
private const val URC_FIELD = "URC" | ||
private const val DL_FIELD = "DL" | ||
|
||
fun JsonNode.urcs(): List<String> = this[URC_FIELD].filter { it.isTextual }.map { it.asText() } | ||
|
||
fun JsonNode.downlinks(): List<String> = | ||
this[URC_FIELD].first { it.isObject }[DL_FIELD].asText().replace("!", "").split(";") | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
...ain/kotlin/org/gxf/crestdeviceservice/command/resulthandler/CommandResultHandlerConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.resulthandler | ||
|
||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
|
||
@Configuration | ||
class CommandResultHandlerConfig { | ||
|
||
@Bean | ||
fun commandResultHandlersByType(commandResultHandlers: List<CommandResultHandler>) = | ||
commandResultHandlers.associateBy { it.supportedCommandType } | ||
} |
26 changes: 26 additions & 0 deletions
26
...n/kotlin/org/gxf/crestdeviceservice/command/resulthandler/FirmwareCommandResultHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.resulthandler | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import org.gxf.crestdeviceservice.command.entity.Command.CommandType | ||
import org.gxf.crestdeviceservice.command.service.CommandFeedbackService | ||
import org.gxf.crestdeviceservice.command.service.CommandService | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class FirmwareCommandResultHandler( | ||
val commandService: CommandService, | ||
val commandFeedbackService: CommandFeedbackService | ||
) : CommandResultHandler(commandService, commandFeedbackService) { | ||
|
||
private val succesUrc = "OTA:SUC" | ||
private val errorUrcs = listOf("OTA:CSER", "OTA:HSER", "OTA:RST", "OTA:SWNA", "OTA:FLER") | ||
|
||
override val supportedCommandType = CommandType.FIRMWARE | ||
|
||
override fun hasSucceeded(deviceId: String, body: JsonNode) = succesUrc in body.urcs() | ||
|
||
override fun hasFailed(deviceId: String, body: JsonNode) = body.urcs().any { it in errorUrcs } | ||
} |
24 changes: 24 additions & 0 deletions
24
...c/main/kotlin/org/gxf/crestdeviceservice/command/resulthandler/PskCommandResultHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.resulthandler | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import org.gxf.crestdeviceservice.command.entity.Command.CommandType | ||
import org.gxf.crestdeviceservice.command.service.CommandFeedbackService | ||
import org.gxf.crestdeviceservice.command.service.CommandService | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class PskCommandResultHandler(commandService: CommandService, commandFeedbackService: CommandFeedbackService) : | ||
CommandResultHandler(commandService, commandFeedbackService) { | ||
|
||
private val succesUrc = "PSK:TMP" | ||
private val errorUrcs = listOf("PSK:DLER", "PSK:HSER") | ||
|
||
override val supportedCommandType = CommandType.PSK | ||
|
||
override fun hasSucceeded(deviceId: String, body: JsonNode) = succesUrc in body.urcs() | ||
|
||
override fun hasFailed(deviceId: String, body: JsonNode) = body.urcs().any { it in errorUrcs } | ||
} |
42 changes: 42 additions & 0 deletions
42
...ain/kotlin/org/gxf/crestdeviceservice/command/resulthandler/PskSetCommandResultHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.resulthandler | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.gxf.crestdeviceservice.command.entity.Command | ||
import org.gxf.crestdeviceservice.command.entity.Command.CommandType | ||
import org.gxf.crestdeviceservice.command.service.CommandFeedbackService | ||
import org.gxf.crestdeviceservice.command.service.CommandService | ||
import org.gxf.crestdeviceservice.psk.service.PskService | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class PskSetCommandResultHandler( | ||
val pskService: PskService, | ||
val commandService: CommandService, | ||
val commandFeedbackService: CommandFeedbackService | ||
) : CommandResultHandler(commandService, commandFeedbackService) { | ||
|
||
private val logger = KotlinLogging.logger {} | ||
|
||
private val succesUrc = "PSK:SET" | ||
private val errorUrcs = listOf("PSK:DLER", "PSK:HSER", "PSK:EQER") | ||
|
||
override val supportedCommandType = CommandType.PSK_SET | ||
|
||
override fun hasSucceeded(deviceId: String, body: JsonNode) = succesUrc in body.urcs() | ||
|
||
override fun hasFailed(deviceId: String, body: JsonNode) = body.urcs().any { it in errorUrcs } | ||
|
||
override fun handleCommandSpecificSuccess(command: Command) { | ||
logger.info { "PSK SET command succeeded: Changing active key for device ${command.deviceId}" } | ||
pskService.changeActiveKey(command.deviceId) | ||
} | ||
|
||
override fun handleCommandSpecificFailure(command: Command, body: JsonNode) { | ||
logger.info { "PSK SET command failed: Setting pending key as invalid for device ${command.deviceId}" } | ||
pskService.setPendingKeyAsInvalid(command.deviceId) | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
...ain/kotlin/org/gxf/crestdeviceservice/command/resulthandler/RebootCommandResultHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.resulthandler | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import org.gxf.crestdeviceservice.command.entity.Command.CommandType | ||
import org.gxf.crestdeviceservice.command.service.CommandFeedbackService | ||
import org.gxf.crestdeviceservice.command.service.CommandService | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class RebootCommandResultHandler(commandService: CommandService, commandFeedbackService: CommandFeedbackService) : | ||
CommandResultHandler(commandService, commandFeedbackService) { | ||
|
||
private val succesUrcs = listOf("INIT", "WDR") | ||
|
||
override val supportedCommandType = CommandType.REBOOT | ||
|
||
override fun hasSucceeded(deviceId: String, body: JsonNode) = body.urcs().containsAll(succesUrcs) | ||
|
||
override fun hasFailed(deviceId: String, body: JsonNode) = false | ||
} |
19 changes: 19 additions & 0 deletions
19
.../main/kotlin/org/gxf/crestdeviceservice/command/resulthandler/Rsp2CommandResultHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.resulthandler | ||
|
||
import org.gxf.crestdeviceservice.command.entity.Command.CommandType | ||
import org.gxf.crestdeviceservice.command.service.CommandFeedbackService | ||
import org.gxf.crestdeviceservice.command.service.CommandService | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class Rsp2CommandResultHandler(commandService: CommandService, commandFeedbackService: CommandFeedbackService) : | ||
RspCommandResultHandler(commandService, commandFeedbackService) { | ||
|
||
override val confirmationDownlinkInUrc = "CMD:RSP2" | ||
override val errorUrc = "RSP2:DLER" | ||
|
||
override val supportedCommandType = CommandType.RSP2 | ||
} |
25 changes: 25 additions & 0 deletions
25
...c/main/kotlin/org/gxf/crestdeviceservice/command/resulthandler/RspCommandResultHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.resulthandler | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import org.gxf.crestdeviceservice.command.entity.Command.CommandType | ||
import org.gxf.crestdeviceservice.command.service.CommandFeedbackService | ||
import org.gxf.crestdeviceservice.command.service.CommandService | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class RspCommandResultHandler(commandService: CommandService, commandFeedbackService: CommandFeedbackService) : | ||
CommandResultHandler(commandService, commandFeedbackService) { | ||
|
||
val confirmationDownlinkInUrc = "CMD:RSP" | ||
val errorUrc = "RSP:DLER" | ||
|
||
override val supportedCommandType = CommandType.RSP | ||
|
||
override fun hasSucceeded(deviceId: String, body: JsonNode) = | ||
confirmationDownlinkInUrc in body.downlinks() && errorUrc !in body.urcs() | ||
|
||
override fun hasFailed(deviceId: String, body: JsonNode) = errorUrc in body.urcs() | ||
} |
41 changes: 41 additions & 0 deletions
41
...cation/src/main/kotlin/org/gxf/crestdeviceservice/command/service/CommandResultService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdeviceservice.command.service | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.gxf.crestdeviceservice.command.entity.Command | ||
import org.gxf.crestdeviceservice.command.exception.NoCommandResultHandlerForCommandTypeException | ||
import org.gxf.crestdeviceservice.command.resulthandler.CommandResultHandler | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class CommandResultService( | ||
private val commandService: CommandService, | ||
private val commandResultHandlersByType: Map<Command.CommandType, CommandResultHandler> | ||
) { | ||
private val logger = KotlinLogging.logger {} | ||
|
||
fun handleMessage(deviceId: String, body: JsonNode) { | ||
val commandsInProgress = commandService.getAllCommandsInProgressForDevice(deviceId) | ||
|
||
commandsInProgress.forEach { checkResult(it, body) } | ||
} | ||
|
||
private fun checkResult(command: Command, body: JsonNode) { | ||
logger.debug { "Checking result for pending command of type ${command.type} for device ${command.deviceId}" } | ||
|
||
val resultHandler = | ||
commandResultHandlersByType[command.type] | ||
?: throw NoCommandResultHandlerForCommandTypeException( | ||
"No command result handler for command type ${command.type}" | ||
) | ||
|
||
when { | ||
resultHandler.hasSucceeded(command.deviceId, body) -> resultHandler.handleSuccess(command) | ||
resultHandler.hasFailed(command.deviceId, body) -> resultHandler.handleFailure(command, body) | ||
else -> resultHandler.handleStillInProgress(command) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.