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