157 lines
5.3 KiB
Kotlin
157 lines
5.3 KiB
Kotlin
package sbc
|
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.launch
|
|
import org.slf4j.LoggerFactory
|
|
import somecodes.Codes.Companion.gpioExportPath
|
|
import somecodes.Codes.Companion.gpioPath
|
|
import somecodes.Codes.Companion.gpioUnexportPath
|
|
import somecodes.Codes.Companion.haveGpioSupport
|
|
import java.nio.file.Files
|
|
import java.nio.file.Path
|
|
import kotlin.io.path.isDirectory
|
|
|
|
/**
|
|
* Create a digital output for a GPIO pin.
|
|
* @param linuxGpio The GPIO pin number in Linux.
|
|
* @param name The name of the digital output.
|
|
* @param activeHigh If true, the output is active high (default is true).
|
|
* @property inited Indicates whether the digital output has been initialized.
|
|
*
|
|
*/
|
|
@Suppress("unused")
|
|
class DigitalOutput(val linuxGpio: Int, val name: String, val activeHigh: Boolean = true) {
|
|
var inited = false; private set
|
|
private var valuepath: Path? = null
|
|
private val logger = LoggerFactory.getLogger("DigitalOutput $name ($linuxGpio)")
|
|
init{
|
|
if (haveGpioSupport()){
|
|
if (checkExists()){
|
|
// already exists
|
|
try{
|
|
// try to set direction to output
|
|
val dir = gpioPath.resolve("gpio$linuxGpio").resolve("direction")
|
|
Files.writeString(dir, "out")
|
|
// successfully set direction to output
|
|
inited = true
|
|
valuepath = gpioPath.resolve("gpio$linuxGpio").resolve("value")
|
|
logger.info("GPIO $name GPIO $linuxGpio already exists as output")
|
|
} catch (e : Exception){
|
|
// failed to set direction to output, log error
|
|
logger.error("Failed to set existing GPIO $name GPIO $linuxGpio as output: ${e.message}")
|
|
}
|
|
|
|
} else {
|
|
// not yet exists, export it
|
|
try{
|
|
// export the GPIO pin
|
|
Files.writeString(gpioExportPath, linuxGpio.toString())
|
|
if (checkExists()){
|
|
// successfully exported, now set direction to output
|
|
val dir = gpioPath.resolve("gpio$linuxGpio").resolve("direction")
|
|
Files.writeString(dir, "out")
|
|
inited = true
|
|
valuepath = gpioPath.resolve("gpio$linuxGpio").resolve("value")
|
|
logger.info("Initialized GPIO $name GPIO $linuxGpio as output")
|
|
} else {
|
|
// failed to export, log error
|
|
logger.error("GPIO $name GPIO $linuxGpio does not exist after export")
|
|
}
|
|
|
|
|
|
} catch (e: Exception){
|
|
// failed to export GPIO pin, log error
|
|
logger.error("Failed to export GPIO $name GPIO $linuxGpio: ${e.message}")
|
|
}
|
|
}
|
|
|
|
|
|
} else logger.error("DigitalOutput $name GPIO $linuxGpio not initialized: GPIO support not available")
|
|
}
|
|
|
|
fun checkExists(): Boolean{
|
|
return try {
|
|
val gpioPath = gpioPath.resolve("gpio$linuxGpio")
|
|
if (gpioPath.isDirectory() && gpioPath.toFile().exists()){
|
|
val dir = gpioPath.resolve("direction").toFile()
|
|
val value = gpioPath.resolve("value").toFile()
|
|
if (dir.exists() && value.exists()) {
|
|
return dir.canWrite() && value.canWrite()
|
|
}
|
|
}
|
|
false
|
|
} catch (e: Exception) {
|
|
logger.error("Error checking if GPIO $linuxGpio exists: ${e.message}")
|
|
false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Release the GPIO pin by unexporting it.
|
|
*/
|
|
fun release(){
|
|
if (inited){
|
|
try{
|
|
Files.writeString(gpioUnexportPath, linuxGpio.toString())
|
|
inited = false
|
|
valuepath = null
|
|
} catch (e : Exception){
|
|
logger.error("Failed to unexport GPIO $name GPIO ${e.message}")
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set Digital Output to ON
|
|
*/
|
|
fun setON() : Boolean{
|
|
if (inited){
|
|
if (valuepath!=null){
|
|
try{
|
|
Files.writeString(valuepath!!, if (activeHigh) "1" else "0")
|
|
return true
|
|
} catch (e: Exception){
|
|
logger.error("Failed to set GPIO $name GPIO $linuxGpio ON: ${e.message}")
|
|
}
|
|
}
|
|
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Set Digital Output to OFF
|
|
*/
|
|
fun setOFF() : Boolean{
|
|
if (inited){
|
|
if (valuepath!=null){
|
|
try{
|
|
Files.writeString(valuepath!!, if (activeHigh) "0" else "1")
|
|
return true
|
|
} catch (e : Exception){
|
|
logger.error("Failed to set GPIO $name GPIO $linuxGpio OFF: ${e.message}")
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Blink the Digital Output for a specified duration.
|
|
* @param ms The duration in milliseconds to keep the output ON before turning it OFF (default is 50ms).
|
|
*/
|
|
fun Blink(ms: Long = 50){
|
|
if (inited){
|
|
CoroutineScope(Dispatchers.IO).launch {
|
|
setON()
|
|
delay(ms)
|
|
setOFF()
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} |