Skip to content

Add Kotlin examples #85

Closed
Closed

Description

@Omnieboer

I'm not sure how to propose edits to the wiki, but I have re-created the examples on the wiki in Kotlin, if you are interested in adding them. I haven't found a Kotlin-specific SerialPort library that isn't based on Android, so I figure all Kotlin users looking for a SerialPort will come here.

Following is my example code:

import jssc.*
import jssc.SerialPort.*

fun main() {
    listPorts()
    writeData()
    readData()
    eventListener()
}
// #List Ports
fun listPorts() {
    val ports = SerialPortList.getPortNames()
    ports.forEach { println(it) }
}

// #Write Data
fun writeData() {
    val port = SerialPort("COM10")
    port.openPort()
    port.setParams(BAUDRATE_115200, DATABITS_8, STOPBITS_1, PARITY_NONE)
    // port.setParams(9600, 8, 1, 0); // alternate technique
    port.writeBytes("Testing serial from Kotlin".encodeToByteArray())
    // The following shows up in the serial port (prettified for readability):
    // 54 65 73 74 69 6E 67 20 73 65 72 69 61 6C 20 66 72 6F 6D 20 4B 6F 74 6C 69 6E
    port.closePort()
}

// #Read Data
fun readData() {
    val port = SerialPort("COM10")
    port.openPort()
    port.setParams(BAUDRATE_115200, DATABITS_8, STOPBITS_1, PARITY_NONE)
    // port.setParams(9600, 8, 1, 0); // alternate technique
    val buffer = port.readBytes(10 /* read the first 10 bytes */)
    // Print the buffer but pretty, with spaces between bytes and padding to two characters with 0
    // See below for implementation
    println(buffer.fancyToString())
    // Using the same bytes as used in the writeData() method above we get:
    // 54 65 73 74 69 6E 67 20 73 65 72 69 61 6C 20 66 72 6F 6D 20 4B 6F 74 6C 69 6E
    port.closePort()
}

// #Event Listener
fun eventListener() {
    val port = SerialPort("COM10")
    port.openPort()
    port.setParams(BAUDRATE_115200, DATABITS_8, STOPBITS_1, PARITY_NONE)
    // port.setParams(9600, 8, 1, 0); // alternate technique
    val mask = MASK_RXCHAR + MASK_CTS + MASK_DSR
    port.eventsMask = mask
    port.addEventListener(MyPortListener(port))
}

/*
 * In this class must implement the method serialEvent, through it we learn about
 * events that happened to our port. But we will not report on all events but only
 * those that we put in the mask. In this case the arrival of the data and change the
 * status lines CTS and DSR
 */
internal class MyPortListener(private val port: SerialPort) :
    SerialPortEventListener {
    override fun serialEvent(event: SerialPortEvent) {
        when {
            event.isRXCHAR -> { // data is available
                // read data, if 10 bytes available
                if (event.eventValue == 10) {
                    try {
                        println(port.readBytes(10).fancyToString())
                    } catch (ex: SerialPortException) {
                        println(ex)
                    }
                }
            }
            event.isCTS -> { // CTS line has changed state
                if (event.eventValue == 1) { // line is ON
                    println("CTS - ON")
                } else {
                    println("CTS - OFF")
                }
            }
            event.isDSR -> { // DSR line has changed state
                if (event.eventValue == 1) { // line is ON
                    println("DSR - ON")
                } else {
                    println("DSR - OFF")
                }
            }
        }
    }
}

// Please note that Unsigned Integers are a stable feature in Kotlin version >= 1.5
// This is an extension function for ByteArrays to print them as unsigned hexadecimals
private fun ByteArray.fancyToString(): String {
    var res = ""
    // Converts each element from a signed byte to a unsigned byte
    this.asUByteArray().forEach {
        // Returns the bytes as two hexadecimals, separated by spaces per pair. Fills out the leading zero if necessary
        res += it.toString(16).toUpperCase().padStart(2, '0').padEnd(3, ' ')
    }
    // And remove the trailing whitespace
    return res.trim()
}

I'm not sure how, in the original example, the MyPortListener class has access to the port, because I had to pass the port to it. It does work and prints reactively from the serial messages I'm sending to the relevant port. Otherwise, aside from the fancyToString method, this is basically an exact copy of the current examples on the wiki.

Feel free to disregard and/or close this issue if Kotlin is not applicable to this Repo, but I think there is at least some audience for SerialPorts in Kotlin, and this Repo seems the best/only option.

Activity

  1. tresf commented on Apr 29, 2021

    @tresf

    Thanks. Generally, the wiki can be directly edited and maintained by anyone. I'm not sure if the permissions are setup properly for this, so I've just committed them directly.

    I've added your code verbatim via: https://github.com/java-native/jssc/wiki

    I added a new page, then crosslinked to wiki/Home.

    I'm not sure how, in the original example, the MyPortListener class has access to the port, because I had to pass the port to it. It does work and prints reactively from the serial messages I'm sending to the relevant port.

    I didn't write this but rather copied it blindly from the upstream repo. We'll take a look and adjust accordingly.

  2. Omnieboer commented on Apr 29, 2021

    @Omnieboer
    Author

    Cool, thanks! If you need and/or want any further help, let me know ;)

  3. tresf commented on Apr 29, 2021

    @tresf

    I'm not sure how, in the original example, the MyPortListener class has access to the port, because I had to pass the port to it.

    You're right, the example was wrong. I've fixed it here: https://github.com/java-native/jssc/wiki/Examples/_compare/c3412f125645151ad4378c32b5a8ae220ddda3c0...a1bb82fa756297846cf55d6c06fea8b2ac98e2c6.

    It could technically work in the original example had MyPortListener been non-static AND if the package private variable port were effectively final and internally referenced, but this is non-standard design. Your approach is much better. :)

  4. Omnieboer commented on Apr 30, 2021

    @Omnieboer
    Author

    I have proposed another way to deal with this in #87 . I could also having an overload to allow for both options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions