Replace JSSC with JSerialComm

This commit is contained in:
Alexander Nozik 2023-08-16 10:37:02 +03:00
parent fa4f578a64
commit 69617e73b4
9 changed files with 97 additions and 106 deletions

View File

@ -73,7 +73,7 @@ public class ChannelPort(
} }
/** /**
* A [PortFactory] for TCP connections * A [PortFactory] for TCP services
*/ */
public object TcpPort : PortFactory { public object TcpPort : PortFactory {
@ -97,7 +97,7 @@ public object TcpPort : PortFactory {
/** /**
* A [PortFactory] for UDP connections * A [PortFactory] for UDP services
*/ */
public object UdpPort : PortFactory { public object UdpPort : PortFactory {

View File

@ -5,5 +5,5 @@ plugins {
dependencies{ dependencies{
api(project(":controls-core")) api(project(":controls-core"))
implementation("org.scream3r:jssc:2.8.0") implementation("com.fazecast:jSerialComm:2.10.3")
} }

View File

@ -0,0 +1,87 @@
package space.kscience.controls.serial
import com.fazecast.jSerialComm.SerialPort
import com.fazecast.jSerialComm.SerialPortDataListener
import com.fazecast.jSerialComm.SerialPortEvent
import kotlinx.coroutines.launch
import space.kscience.controls.ports.AbstractPort
import space.kscience.controls.ports.Port
import space.kscience.controls.ports.PortFactory
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.string
import kotlin.coroutines.CoroutineContext
/**
* A port based on JSerialComm
*/
public class JSerialCommPort(
context: Context,
private val comPort: SerialPort,
coroutineContext: CoroutineContext = context.coroutineContext,
) : AbstractPort(context, coroutineContext) {
override fun toString(): String = "port[${comPort.descriptivePortName}]"
private val serialPortListener = object : SerialPortDataListener {
override fun getListeningEvents(): Int = SerialPort.LISTENING_EVENT_DATA_AVAILABLE
override fun serialEvent(event: SerialPortEvent) {
if (event.eventType == SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
scope.launch { receive(event.receivedData) }
}
}
}
init {
comPort.addDataListener(serialPortListener)
}
override suspend fun write(data: ByteArray) {
comPort.writeBytes(data, data.size)
}
override fun close() {
comPort.removeDataListener()
if (comPort.isOpen) {
comPort.closePort()
}
super.close()
}
public companion object : PortFactory {
override val type: String = "com"
/**
* Construct ComPort with given parameters
*/
public fun open(
context: Context,
portName: String,
baudRate: Int = 9600,
dataBits: Int = 8,
stopBits: Int = SerialPort.ONE_STOP_BIT,
parity: Int = SerialPort.NO_PARITY,
coroutineContext: CoroutineContext = context.coroutineContext,
): JSerialCommPort {
val serialPort = SerialPort.getCommPort(portName).apply {
setComPortParameters(baudRate, dataBits, stopBits, parity)
openPort()
}
return JSerialCommPort(context, serialPort, coroutineContext)
}
override fun build(context: Context, meta: Meta): Port {
val name by meta.string { error("Serial port name not defined") }
val baudRate by meta.int(9600)
val dataBits by meta.int(8)
val stopBits by meta.int(SerialPort.ONE_STOP_BIT)
val parity by meta.int(SerialPort.NO_PARITY)
return open(context, name, baudRate, dataBits, stopBits, parity)
}
}
}

View File

@ -1,93 +0,0 @@
package space.kscience.controls.serial
import jssc.SerialPort.*
import jssc.SerialPortEventListener
import kotlinx.coroutines.launch
import space.kscience.controls.ports.AbstractPort
import space.kscience.controls.ports.Port
import space.kscience.controls.ports.PortFactory
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.string
import kotlin.coroutines.CoroutineContext
import jssc.SerialPort as JSSCPort
/**
* COM/USB port
*/
public class SerialPort private constructor(
context: Context,
private val jssc: JSSCPort,
coroutineContext: CoroutineContext = context.coroutineContext,
) : AbstractPort(context, coroutineContext) {
override fun toString(): String = "port[${jssc.portName}]"
private val serialPortListener = SerialPortEventListener { event ->
if (event.isRXCHAR) {
val chars = event.eventValue
val bytes = jssc.readBytes(chars)
scope.launch { receive(bytes) }
}
}
init {
jssc.addEventListener(serialPortListener)
}
/**
* Clear current input and output buffers
*/
internal fun clearPort() {
jssc.purgePort(PURGE_RXCLEAR or PURGE_TXCLEAR)
}
override suspend fun write(data: ByteArray) {
jssc.writeBytes(data)
}
@Throws(Exception::class)
override fun close() {
jssc.removeEventListener()
clearPort()
if (jssc.isOpened) {
jssc.closePort()
}
super.close()
}
public companion object : PortFactory {
override val type: String = "com"
/**
* Construct ComPort with given parameters
*/
public fun open(
context: Context,
portName: String,
baudRate: Int = BAUDRATE_9600,
dataBits: Int = DATABITS_8,
stopBits: Int = STOPBITS_1,
parity: Int = PARITY_NONE,
coroutineContext: CoroutineContext = context.coroutineContext,
): SerialPort {
val jssc = JSSCPort(portName).apply {
openPort()
setParams(baudRate, dataBits, stopBits, parity)
}
return SerialPort(context, jssc, coroutineContext)
}
override fun build(context: Context, meta: Meta): Port {
val name by meta.string { error("Serial port name not defined") }
val baudRate by meta.int(BAUDRATE_9600)
val dataBits by meta.int(DATABITS_8)
val stopBits by meta.int(STOPBITS_1)
val parity by meta.int(PARITY_NONE)
return open(context, name, baudRate, dataBits, stopBits, parity)
}
}
}

View File

@ -13,7 +13,7 @@ public class SerialPortPlugin : AbstractPlugin() {
override val tag: PluginTag get() = Companion.tag override val tag: PluginTag get() = Companion.tag
override fun content(target: String): Map<Name, Any> = when(target){ override fun content(target: String): Map<Name, Any> = when(target){
PortFactory.TYPE -> mapOf(Name.EMPTY to SerialPort) PortFactory.TYPE -> mapOf(Name.EMPTY to JSerialCommPort)
else -> emptyMap() else -> emptyMap()
} }

View File

@ -1,3 +0,0 @@
subprojects{
}

View File

@ -28,22 +28,22 @@ public interface MagixEndpoint {
public companion object { public companion object {
/** /**
* A default port for HTTP/WS connections * A default port for HTTP/WS services
*/ */
public const val DEFAULT_MAGIX_HTTP_PORT: Int = 7777 public const val DEFAULT_MAGIX_HTTP_PORT: Int = 7777
/** /**
* A default port for raw TCP connections * A default port for raw TCP services
*/ */
public const val DEFAULT_MAGIX_RAW_PORT: Int = 7778 public const val DEFAULT_MAGIX_RAW_PORT: Int = 7778
/** /**
* A default PUB port for ZMQ connections * A default PUB port for ZMQ services
*/ */
public const val DEFAULT_MAGIX_ZMQ_PUB_PORT: Int = 7781 public const val DEFAULT_MAGIX_ZMQ_PUB_PORT: Int = 7781
/** /**
* A default PULL port for ZMQ connections * A default PULL port for ZMQ services
*/ */
public const val DEFAULT_MAGIX_ZMQ_PULL_PORT: Int = 7782 public const val DEFAULT_MAGIX_ZMQ_PULL_PORT: Int = 7782

View File

@ -1,4 +1,4 @@
package space.kscience.magix.connections package space.kscience.magix.services
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job

@ -1 +1 @@
Subproject commit 5ae42aa297fbd2ab2239601f064e1d1239487590 Subproject commit 7f50062bd42dd5046110326cae2492ad1f7a195f