modbus registry to json rendering
This commit is contained in:
parent
290010fc8c
commit
7f71d0c9e9
@ -1,4 +1,3 @@
|
||||
import space.kscience.gradle.isInDevelopment
|
||||
import space.kscience.gradle.useApache2Licence
|
||||
import space.kscience.gradle.useSPCTeam
|
||||
|
||||
@ -14,25 +13,18 @@ val xodusVersion by extra("2.0.1")
|
||||
|
||||
allprojects {
|
||||
group = "space.kscience"
|
||||
version = "0.2.2-dev-2"
|
||||
version = "0.2.2-dev-3"
|
||||
repositories{
|
||||
maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev")
|
||||
}
|
||||
}
|
||||
|
||||
ksciencePublish {
|
||||
pom("https://github.com/SciProgCentre/controls.kt") {
|
||||
pom("https://github.com/SciProgCentre/controls-kt") {
|
||||
useApache2Licence()
|
||||
useSPCTeam()
|
||||
}
|
||||
github("controls.kt", "SciProgCentre")
|
||||
space(
|
||||
if (isInDevelopment) {
|
||||
"https://maven.pkg.jetbrains.space/spc/p/sci/dev"
|
||||
} else {
|
||||
"https://maven.pkg.jetbrains.space/spc/p/sci/maven"
|
||||
}
|
||||
)
|
||||
repository("spc","https://maven.sciprog.center/kscience")
|
||||
sonatype("https://oss.sonatype.org")
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import io.ktor.utils.io.core.readBytes
|
||||
import io.ktor.utils.io.core.reset
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.transform
|
||||
|
||||
/**
|
||||
@ -16,6 +17,10 @@ public fun Flow<ByteArray>.withDelimiter(delimiter: ByteArray): Flow<ByteArray>
|
||||
val output = BytePacketBuilder()
|
||||
var matcherPosition = 0
|
||||
|
||||
onCompletion {
|
||||
output.close()
|
||||
}
|
||||
|
||||
return transform { chunk ->
|
||||
chunk.forEach { byte ->
|
||||
output.writeByte(byte)
|
||||
|
@ -12,7 +12,7 @@ description = """
|
||||
|
||||
dependencies {
|
||||
api(projects.controlsCore)
|
||||
api("com.ghgande:j2mod:3.1.1")
|
||||
api("com.ghgande:j2mod:3.2.0")
|
||||
}
|
||||
|
||||
readme{
|
||||
|
@ -1,8 +1,15 @@
|
||||
package space.kscience.controls.modbus
|
||||
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.buildJsonArray
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
import space.kscience.dataforge.io.IOFormat
|
||||
|
||||
|
||||
/**
|
||||
* Modbus registry key
|
||||
*/
|
||||
public sealed class ModbusRegistryKey {
|
||||
public abstract val address: Int
|
||||
public open val count: Int = 1
|
||||
@ -25,6 +32,9 @@ public sealed class ModbusRegistryKey {
|
||||
override fun toString(): String = "InputRegister(address=$address)"
|
||||
}
|
||||
|
||||
/**
|
||||
* A range of read-only register encoding a single value
|
||||
*/
|
||||
public class InputRange<T>(
|
||||
address: Int,
|
||||
override val count: Int,
|
||||
@ -36,10 +46,16 @@ public sealed class ModbusRegistryKey {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A single read-write register
|
||||
*/
|
||||
public open class HoldingRegister(override val address: Int) : ModbusRegistryKey() {
|
||||
override fun toString(): String = "HoldingRegister(address=$address)"
|
||||
}
|
||||
|
||||
/**
|
||||
* A range of read-write registers encoding a single value
|
||||
*/
|
||||
public class HoldingRange<T>(
|
||||
address: Int,
|
||||
override val count: Int,
|
||||
@ -52,6 +68,9 @@ public sealed class ModbusRegistryKey {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A base class for modbus registers
|
||||
*/
|
||||
public abstract class ModbusRegistryMap {
|
||||
|
||||
private val _entries: MutableMap<ModbusRegistryKey, String> = mutableMapOf<ModbusRegistryKey, String>()
|
||||
@ -63,36 +82,56 @@ public abstract class ModbusRegistryMap {
|
||||
return key
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a [ModbusRegistryKey.Coil] key and return it
|
||||
*/
|
||||
protected fun coil(address: Int, description: String = ""): ModbusRegistryKey.Coil =
|
||||
register(ModbusRegistryKey.Coil(address), description)
|
||||
|
||||
|
||||
/**
|
||||
* Register a [ModbusRegistryKey.DiscreteInput] key and return it
|
||||
*/
|
||||
protected fun discrete(address: Int, description: String = ""): ModbusRegistryKey.DiscreteInput =
|
||||
register(ModbusRegistryKey.DiscreteInput(address), description)
|
||||
|
||||
/**
|
||||
* Register a [ModbusRegistryKey.InputRegister] key and return it
|
||||
*/
|
||||
protected fun input(address: Int, description: String = ""): ModbusRegistryKey.InputRegister =
|
||||
register(ModbusRegistryKey.InputRegister(address), description)
|
||||
|
||||
/**
|
||||
* Register a [ModbusRegistryKey.InputRange] key and return it
|
||||
*/
|
||||
protected fun <T> input(
|
||||
address: Int,
|
||||
count: Int,
|
||||
reader: IOFormat<T>,
|
||||
description: String = "",
|
||||
): ModbusRegistryKey.InputRange<T> =
|
||||
register(ModbusRegistryKey.InputRange(address, count, reader), description)
|
||||
): ModbusRegistryKey.InputRange<T> = register(ModbusRegistryKey.InputRange(address, count, reader), description)
|
||||
|
||||
/**
|
||||
* Register a [ModbusRegistryKey.HoldingRegister] key and return it
|
||||
*/
|
||||
protected fun register(address: Int, description: String = ""): ModbusRegistryKey.HoldingRegister =
|
||||
register(ModbusRegistryKey.HoldingRegister(address), description)
|
||||
|
||||
/**
|
||||
* Register a [ModbusRegistryKey.HoldingRange] key and return it
|
||||
*/
|
||||
protected fun <T> register(
|
||||
address: Int,
|
||||
count: Int,
|
||||
format: IOFormat<T>,
|
||||
description: String = "",
|
||||
): ModbusRegistryKey.HoldingRange<T> =
|
||||
register(ModbusRegistryKey.HoldingRange(address, count, format), description)
|
||||
): ModbusRegistryKey.HoldingRange<T> = register(ModbusRegistryKey.HoldingRange(address, count, format), description)
|
||||
|
||||
public companion object {
|
||||
|
||||
/**
|
||||
* Validate the register map. Throw an error if the map is invalid
|
||||
*/
|
||||
public fun validate(map: ModbusRegistryMap) {
|
||||
var lastCoil: ModbusRegistryKey.Coil? = null
|
||||
var lastDiscreteInput: ModbusRegistryKey.DiscreteInput? = null
|
||||
@ -127,36 +166,62 @@ public abstract class ModbusRegistryMap {
|
||||
}
|
||||
}
|
||||
|
||||
private val ModbusRegistryKey.sectionNumber
|
||||
get() = when (this) {
|
||||
is ModbusRegistryKey.Coil -> 1
|
||||
is ModbusRegistryKey.DiscreteInput -> 2
|
||||
is ModbusRegistryKey.HoldingRegister -> 4
|
||||
is ModbusRegistryKey.InputRegister -> 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun print(map: ModbusRegistryMap, to: Appendable = System.out) {
|
||||
validate(map)
|
||||
map.entries.entries
|
||||
.sortedWith(
|
||||
Comparator.comparingInt<Map.Entry<ModbusRegistryKey, String>?> { it.key.sectionNumber }
|
||||
.thenComparingInt { it.key.address }
|
||||
)
|
||||
.forEach { (key, description) ->
|
||||
val typeString = when (key) {
|
||||
is ModbusRegistryKey.Coil -> "Coil"
|
||||
is ModbusRegistryKey.DiscreteInput -> "Discrete"
|
||||
is ModbusRegistryKey.HoldingRegister -> "Register"
|
||||
is ModbusRegistryKey.InputRegister -> "Input"
|
||||
}
|
||||
val rangeString = if (key.count == 1) {
|
||||
key.address.toString()
|
||||
} else {
|
||||
"${key.address} - ${key.address + key.count - 1}"
|
||||
}
|
||||
to.appendLine("${typeString}\t$rangeString\t$description")
|
||||
}
|
||||
private val ModbusRegistryKey.sectionNumber
|
||||
get() = when (this) {
|
||||
is ModbusRegistryKey.Coil -> 1
|
||||
is ModbusRegistryKey.DiscreteInput -> 2
|
||||
is ModbusRegistryKey.HoldingRegister -> 4
|
||||
is ModbusRegistryKey.InputRegister -> 3
|
||||
}
|
||||
|
||||
public fun ModbusRegistryMap.print(to: Appendable = System.out) {
|
||||
ModbusRegistryMap.validate(this)
|
||||
entries.entries
|
||||
.sortedWith(
|
||||
Comparator.comparingInt<Map.Entry<ModbusRegistryKey, String>?> { it.key.sectionNumber }
|
||||
.thenComparingInt { it.key.address }
|
||||
)
|
||||
.forEach { (key, description) ->
|
||||
val typeString = when (key) {
|
||||
is ModbusRegistryKey.Coil -> "Coil"
|
||||
is ModbusRegistryKey.DiscreteInput -> "Discrete"
|
||||
is ModbusRegistryKey.HoldingRegister -> "Register"
|
||||
is ModbusRegistryKey.InputRegister -> "Input"
|
||||
}
|
||||
val rangeString = if (key.count == 1) {
|
||||
key.address.toString()
|
||||
} else {
|
||||
"${key.address} - ${key.address + key.count - 1}"
|
||||
}
|
||||
to.appendLine("${typeString}\t$rangeString\t$description")
|
||||
}
|
||||
}
|
||||
|
||||
public fun ModbusRegistryMap.toJson(): JsonArray = buildJsonArray {
|
||||
ModbusRegistryMap.validate(this@toJson)
|
||||
entries.forEach { (key, description) ->
|
||||
|
||||
val entry = buildJsonObject {
|
||||
put(
|
||||
"type",
|
||||
when (key) {
|
||||
is ModbusRegistryKey.Coil -> "Coil"
|
||||
is ModbusRegistryKey.DiscreteInput -> "Discrete"
|
||||
is ModbusRegistryKey.HoldingRegister -> "Register"
|
||||
is ModbusRegistryKey.InputRegister -> "Input"
|
||||
}
|
||||
)
|
||||
put("address", key.address)
|
||||
if (key.count > 1) {
|
||||
put("count", key.count)
|
||||
}
|
||||
put("description", description)
|
||||
}
|
||||
|
||||
add(entry)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,4 +10,4 @@ publishing.sonatype=false
|
||||
org.gradle.configureondemand=true
|
||||
org.gradle.jvmargs=-Xmx4096m
|
||||
|
||||
toolsVersion=0.14.10-kotlin-1.9.0
|
||||
toolsVersion=0.15.0-kotlin-1.9.20-RC
|
Loading…
Reference in New Issue
Block a user