Add Pi serial port

This commit is contained in:
Alexander Nozik 2023-05-19 20:27:08 +03:00
parent 28cb9af267
commit a5a2edc81a
3 changed files with 70 additions and 11 deletions

View File

@ -15,7 +15,7 @@ import java.nio.channels.DatagramChannel
import java.nio.channels.SocketChannel import java.nio.channels.SocketChannel
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
internal fun ByteBuffer.readArray(limit: Int = limit()): ByteArray { public fun ByteBuffer.toArray(limit: Int = limit()): ByteArray {
rewind() rewind()
val response = ByteArray(limit) val response = ByteArray(limit)
get(response) get(response)
@ -48,7 +48,7 @@ public class ChannelPort (
try { try {
val num = channel.read(buffer) val num = channel.read(buffer)
if (num > 0) { if (num > 0) {
receive(buffer.readArray(num)) receive(buffer.toArray(num))
} }
if (num < 0) cancel("The input channel is exhausted") if (num < 0) cancel("The input channel is exhausted")
} catch (ex: Exception) { } catch (ex: Exception) {

View File

@ -0,0 +1,19 @@
package space.kscience.controls.pi
import space.kscience.dataforge.context.AbstractPlugin
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.PluginFactory
import space.kscience.dataforge.context.PluginTag
import space.kscience.dataforge.meta.Meta
public class PiPlugin : AbstractPlugin() {
override val tag: PluginTag get() = Companion.tag
public companion object : PluginFactory<PiPlugin> {
override val tag: PluginTag = PluginTag("controls.ports.pi", group = PluginTag.DATAFORGE_GROUP)
override fun build(context: Context, meta: Meta): PiPlugin = PiPlugin()
}
}

View File

@ -1,14 +1,19 @@
package space.kscience.controls.pi package space.kscience.controls.pi
import com.pi4j.io.serial.FlowControl import com.pi4j.Pi4J
import com.pi4j.io.serial.Parity
import com.pi4j.io.serial.Serial import com.pi4j.io.serial.Serial
import com.pi4j.io.serial.StopBits import com.pi4j.io.serial.SerialConfigBuilder
import com.pi4j.ktx.io.open
import com.pi4j.ktx.io.piGpioSerialProvider
import com.pi4j.ktx.io.serial import com.pi4j.ktx.io.serial
import kotlinx.coroutines.*
import space.kscience.controls.ports.AbstractPort import space.kscience.controls.ports.AbstractPort
import space.kscience.controls.ports.Port
import space.kscience.controls.ports.PortFactory
import space.kscience.controls.ports.toArray
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.error
import space.kscience.dataforge.context.logger
import space.kscience.dataforge.meta.Meta
import java.nio.ByteBuffer
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
public class PiSerialPort( public class PiSerialPort(
@ -17,9 +22,44 @@ public class PiSerialPort(
public val serialBuilder: () -> Serial, public val serialBuilder: () -> Serial,
) : AbstractPort(context, coroutineContext) { ) : AbstractPort(context, coroutineContext) {
private val serial by lazy { serialBuilder() } private val serial: Serial by lazy { serialBuilder() }
override suspend fun write(data: ByteArray) {
TODO() private val listenerJob = this.scope.launch(Dispatchers.IO) {
val buffer = ByteBuffer.allocate(1024)
while (isActive) {
try {
val num = serial.read(buffer)
if (num > 0) {
receive(buffer.toArray(num))
}
if (num < 0) cancel("The input channel is exhausted")
} catch (ex: Exception) {
logger.error(ex) { "Channel read error" }
delay(1000)
}
}
} }
}
override suspend fun write(data: ByteArray): Unit = withContext(Dispatchers.IO) {
serial.write(data)
}
override fun close() {
listenerJob.cancel()
serial.close()
}
public companion object : PortFactory {
override val type: String get() = "pi"
public fun open(context: Context, device: String, block: SerialConfigBuilder.() -> Unit): PiSerialPort =
PiSerialPort(context) { Pi4J.newAutoContext().serial(device, block) }
override fun build(context: Context, meta: Meta): Port = PiSerialPort(context) {
Pi4J.newAutoContext().serial()
}
}
}