-
Notifications
You must be signed in to change notification settings - Fork 1
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 #45 from OSGP/feature/FDP-2874-alarm-info
Feature/fdp 2874 alarm info
- Loading branch information
Showing
10 changed files
with
173 additions
and
36 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
73 changes: 73 additions & 0 deletions
73
...otlin/org/gxf/crestdevicesimulator/simulator/response/handlers/InfoAlarmCommandHandler.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.crestdevicesimulator.simulator.response.handlers | ||
|
||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.gxf.crestdevicesimulator.simulator.data.entity.AlarmThresholdValues | ||
import org.gxf.crestdevicesimulator.simulator.data.entity.SimulatorState | ||
import org.gxf.crestdevicesimulator.simulator.response.exception.InvalidCommandException | ||
|
||
/** | ||
* Command Handler for INFO:AL# and INFO:ALARM downlinks. | ||
* | ||
* Gets the alarm thresholds for the specified alarm or for all alarms | ||
* * On success: a downlink containing the alarm thresholds will be returned in the next message sent | ||
* * On failure: "INFO:DLER" URC will be returned in the next message sent | ||
*/ | ||
class InfoAlarmCommandHandler : CommandHandler { | ||
private val logger = KotlinLogging.logger {} | ||
private val commandRegex: Regex = "INFO:AL([2-7]|ARM)".toRegex() | ||
|
||
override fun canHandleCommand(command: String) = commandRegex.matches(command) | ||
|
||
override fun handleCommand(command: String, simulatorState: SimulatorState) { | ||
require(canHandleCommand(command)) { "Info alarm command handler can not handle command: $command" } | ||
try { | ||
handleInfoAlarmCommand(command, simulatorState) | ||
} catch (_: InvalidCommandException) { | ||
handleFailure(command, simulatorState) | ||
} | ||
} | ||
|
||
private fun handleInfoAlarmCommand(command: String, simulatorState: SimulatorState) { | ||
logger.info { "Handling info alarm command: $command" } | ||
try { | ||
simulatorState.addDownlink(command.inQuotes()) | ||
if (isForSpecificAlarm(command)) { | ||
val channel: Int = getChannelFromCommand(command) | ||
val thresholds = | ||
checkNotNull(simulatorState.getAlarmThresholds(channel)) { | ||
"Alarm thresholds for channel $channel not present." | ||
} | ||
simulatorState.addDownlink(thresholds.toJsonString().inBraces()) | ||
} else { | ||
simulatorState.addDownlink(simulatorState.getAlarmThresholds().values.toJsonString()) | ||
} | ||
} catch (ex: Exception) { | ||
throw InvalidCommandException("Invalid info alarm command", ex) | ||
} | ||
} | ||
|
||
private fun handleFailure(command: String, simulatorState: SimulatorState) { | ||
logger.warn { "Handling failure for info alarm command: $command" } | ||
simulatorState.addUrc("INFO:DLER") | ||
simulatorState.addDownlink(command.inQuotes()) | ||
} | ||
|
||
private fun isForSpecificAlarm(command: String) = !isForAllAlarms(command) | ||
|
||
private fun isForAllAlarms(command: String) = command.contains("ALARM") | ||
|
||
private fun getChannelFromCommand(command: String) = command.substringAfter("AL").substringBefore(":").toInt() | ||
|
||
private fun MutableCollection<AlarmThresholdValues>.toJsonString() = | ||
this.joinToString(",") { it.toJsonString() }.inBraces() | ||
|
||
private fun String.inQuotes() = "\"$this\"" | ||
|
||
private fun String.inBraces() = "{$this}" | ||
|
||
private fun AlarmThresholdValues.toJsonString() = | ||
"\"AL${this.channel}\":[${this.veryLow},${this.low},${this.high},${this.veryHigh},${this.hysteresis}]" | ||
} |
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
80 changes: 80 additions & 0 deletions
80
...n/org/gxf/crestdevicesimulator/simulator/response/handlers/InfoAlarmCommandHandlerTest.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,80 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.crestdevicesimulator.simulator.response.handlers | ||
|
||
import org.assertj.core.api.Assertions.assertThat | ||
import org.assertj.core.api.Assertions.assertThatIllegalArgumentException | ||
import org.gxf.crestdevicesimulator.simulator.data.entity.AlarmThresholdValues | ||
import org.gxf.crestdevicesimulator.simulator.data.entity.SimulatorState | ||
import org.gxf.crestdevicesimulator.simulator.message.DeviceMessageDownlink | ||
import org.junit.jupiter.api.BeforeEach | ||
import org.junit.jupiter.api.Test | ||
import org.junit.jupiter.params.ParameterizedTest | ||
import org.junit.jupiter.params.provider.ValueSource | ||
|
||
class InfoAlarmCommandHandlerTest { | ||
private val commandHandler = InfoAlarmCommandHandler() | ||
|
||
private lateinit var simulatorState: SimulatorState | ||
|
||
@BeforeEach | ||
fun setUp() { | ||
simulatorState = SimulatorState(urcs = mutableListOf()) | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = ["INFO:ALARM", "INFO:AL7"]) | ||
fun `canHandleCommand should return true when called with valid command`(command: String) { | ||
val actualResult = commandHandler.canHandleCommand(command) | ||
assertThat(actualResult).isTrue | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = ["INFO", "INFO:", "INFO:AL", "INFO:AL10", "CMD:REBOOT", "CMD:RSP"]) | ||
fun `canHandleCommand should return false when called with invalid command`(command: String) { | ||
val actualResult = commandHandler.canHandleCommand(command) | ||
assertThat(actualResult).isFalse | ||
} | ||
|
||
@Test | ||
fun `handleCommand should handle info alarm command`() { | ||
val command = "INFO:ALARM" | ||
val alarmThresholdValues = AlarmThresholdValues(6, 0, 500, 1000, 1500, 10) | ||
simulatorState.addAlarmThresholds(alarmThresholdValues) | ||
|
||
commandHandler.handleCommand(command, simulatorState) | ||
|
||
val expectedDownlink = | ||
""" | ||
"INFO:ALARM",{"AL0":[0,0,0,0,0],"AL1":[0,0,0,0,0],"AL2":[0,0,0,0,0],"AL3":[0,0,0,0,0], | ||
"AL4":[0,0,0,0,0],"AL5":[0,0,0,0,0],"AL6":[0,500,1000,1500,10],"AL7":[0,0,0,0,0]} | ||
""" | ||
.trimIndent() | ||
.replace("\n", "") | ||
.replace("\r", "") | ||
assertThat(simulatorState.getUrcListForDeviceMessage()).contains(DeviceMessageDownlink(expectedDownlink)) | ||
} | ||
|
||
@Test | ||
fun `handleCommand should handle info alarm command for a specific alarm`() { | ||
val command = "INFO:AL7" | ||
val alarmThresholdValues = AlarmThresholdValues(7, 0, 500, 1000, 1500, 10) | ||
simulatorState.addAlarmThresholds(alarmThresholdValues) | ||
|
||
commandHandler.handleCommand(command, simulatorState) | ||
|
||
val expectedDownlink = """"INFO:AL7",{"AL7":[0,500,1000,1500,10]}""" | ||
assertThat(simulatorState.getUrcListForDeviceMessage()).contains(DeviceMessageDownlink(expectedDownlink)) | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = ["INFO", "INFO:", "INFO:AL", "INFO:AL10", "CMD:REBOOT", "CMD:RSP"]) | ||
fun `handleCommand should throw an exception and not change simulator state when called with invalid command`( | ||
command: String | ||
) { | ||
assertThatIllegalArgumentException().isThrownBy { commandHandler.handleCommand(command, simulatorState) } | ||
|
||
assertThat(simulatorState.getUrcListForDeviceMessage()).doesNotContain(DeviceMessageDownlink(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
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
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